Reputation: 401
I'm developing an application which has several systems (in my case, system is a loadable component in my application which handles a specific task, for example: translation, config handling, audio, etc...). These systems share some common methods so I created an interface:
public interface System {
public void initialize();
public void uninitialize();
}
But each system has its own methods corresponding to the task the system implements. Here is two example of my systems
First one stores settings:
public class SettingsSystem implements System {
@Override
public void initialize() {
// few lines of code here
}
@Override
public void uninitialize() {
// few lines of code here
}
public Object getSetting(String key) {
// returns a setting
}
}
And language system which does translations.
public class LanguageSystem implements System {
@Override
public void initialize() {
// few lines of code here
}
@Override
public void uninitialize() {
// few lines of code here
}
public void setLanguage(String language) {
// sets language
}
public boolean load( String name) {
// loads a file
}
public String translate(String key) {
// returns translation of a key
}
}
I store the System instances in a static HashMap, because I want to reach them in everywhere in my app. I created a static method to return any systems by a key.
public class App {
// note: System is the System interface I created
private static Map<String, System> systems = new HashMap<String, System>();
public static Object getSystem(String key) {
return systems.get(key);
}
}
If I call the App.getSystem() method, it returns me an Object. So If I call...
App.getSystem("settings");
... it will return the correct item as an Object. But the problem is, I can't call the getSetting() method of SettingsSystem because it tells me that there is no such method.
If I implement it this way:
public static System getSystem(String key) {
return systems.get(key);
}
I can call the initialize() or uninitialize() methods but still no getSettings() method available.
What I want is when I call App.getSystem() method, I want it to return the correct type of object that has in it. Example:
App.getSystem("settings"); // I want it to return a SettingsSystem object
// So I can do:
String width = App.getSystem("settings").getSetting("width");
App.getSystem("language"); // I want it to return a LanguageSystem object
// So I can do:
String welcome = App.getSystem("language").translate("hello_world");
How is this possible? Thanks in advance.
UPDATE
Based on your help, I decided to declare getter methods for each system:
public SettingsSystem getSettingsSystem() {
return (SettingsSystem) system.get("settings");
}
Thank you for your advices!
Upvotes: 3
Views: 244
Reputation: 11958
You need to cast to the correct type like this:
SettingsSystem settingSystem = null;
System system = App.getSystem("settings");
if (system instanceof SettingsSystem) {
settingSystem = (SettingSystem) system;
}
settingSystem.getSetting("width");
Of course, do this with relevant null
checks and so on.
I prefer if casting can be avoided however. Could you keep two seperate maps with the implementing classes instead?
Or, since you seem to have several implementations of System
, go with Patricia Shanahan's solution #2, which isolates the casting.
Upvotes: 3
Reputation: 1019
The getSystem() method returns a System instance, so you can only access the method that is defined in the System interface.
If you want to access the method that is defined in the concrete implementation class, you must cast the object to that class first
Upvotes: 1
Reputation: 26185
The type of an expression, including the type of the return from a call, is fixed at compile time. You cannot make the same method, in the same object, have several different return types.
You have two options:
Upvotes: 2
Reputation: 4624
That's because System
class doesn't have that methods. You would need to explicitly cast to specific classes SettingSystem
and LanguageSystem
to have this methods available.
Upvotes: 1