Reputation: 99
I have a superclass called Parameter. There are many different types of parameters and they have different methods of course. The problem is I initialize the Parameter as one of the subs but still it doesn't allow me to use the subclass events!
package com.lbg.c2;
public class Parameter {
private String type;
public static final Parameter NumberParam = new NumberParam();
public static final Parameter StringParam = new StringParam();
public static final Parameter AnyTypeParam = new AnyTypeParam();
public static final Parameter AnimationParam = new AnimationParam();
public static final Parameter AudioParam = new AudioParam();
public static final Parameter CmpParam = new CmpParam();
public static final Parameter ComboOptionParam = new ComboOptionParam();
public static final Parameter ComboParam = new ComboParam();
public static final Parameter KeybParam = new KeybParam();
public static final Parameter LayerParam = new LayerParam();
public static final Parameter LayoutParam = new LayoutParam();
public static final Parameter ObjectParam = new ObjectParam();
public Parameter () {
}
public Parameter (String t) {
type = t;
}
public String getType() {
return type;
}
public static Parameter init (String t) {
if (t.equals("number")) {
return NumberParam;
}
else if (t.equals("string")) {
return StringParam;
}
else if (t.equals("any type")) {
return AnyTypeParam;
}
else if (t.equals("animation")) {
return AnimationParam;
}
else if (t.equals("audio")) {
return AudioParam;
}
else if (t.equals("comparision")) {
return CmpParam;
}
else if (t.equals("combo option")) {
return ComboOptionParam;
}
else if (t.equals("combo")) {
return ComboParam;
}
else if (t.equals("keyboard")) {
return KeybParam;
}
else if (t.equals("layer")) {
return LayerParam;
}
else if (t.equals("layout")) {
return LayoutParam;
}
else if (t.equals("object")) {
return ObjectParam;
}
else {
return new Parameter();
}
}
}
This method is found statically in Parameter class so when you it can init it from the string passed.
add.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String types [] = {"number","string","any type","comparision","combo option",
"combo","object","layer","layout","keyboard","animation","audio"};
JComboBox<String> box = new JComboBox<String>(types);
JLabel text = new JLabel ("Select the parameter type:\n");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(text, BorderLayout.NORTH);
panel.add(box, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(frame, panel, "New Parameter", JOptionPane.QUESTION_MESSAGE);
Parameter p = Parameter.init((String) box.getSelectedItem());
if (p instanceof NumberParam || p instanceof StringParam || p instanceof AnyTypeParam) {
String label = JOptionPane.showInputDialog(frame,"Parameter Label?","New Parameter",JOptionPane.QUESTION_MESSAGE);
p.setLabel(label); // it says it needs casting!!
}
}
});
Here now the Parameter static method must return a a subclass of the Parameter class but still it doesn't allow me. But now it is a subclass then why it doesn't allow me to use its methods?
It's like saying You are a device and then I subclass you to a Phone and you can't call others because you are still known as a device
Upvotes: 0
Views: 192
Reputation: 22553
You can't use the subclass methods because in
Parameter p = Parameter.init((String) box.getSelectedItem());
you are declaring p as type Parameter. You will only ever be able to call the methods declared in Parameter.
You could explicitly cast the created subclass after the fact like so:
Parameter p = Parameter.init((String) box.getSelectedItem());
NumberParameter np = (NumberParameter)p;
But I think you are thinking about java inheritance wrong. The point of the factory pattern is to provide different concrete implementations of an interface like Parameter. This is useful to the extent that the setLabel() method on the different subclasses does something different.
Upvotes: 0
Reputation: 2820
A Parent
class can never knows who are those Child
classes which are inherited from it. If you have define a method in the Child
class it can only be accessed by/called upon Child
class instance . While the reverse in not true, if a method is defined in Parent Class
all the Child class
instances can access it/call it.
Eg:-
Object o = new String("Hi"); //will work because Object is parent class of String
o.trim(); // can't call/will give compilation error because parent Object does not know child String's trim()
if(o.getClass().equals(String.class) ){ // check actual runtime class of o
String ss = (String) o; //typecasting
System.out.println(ss.trim()); // will work on String object
}
Upvotes: 2
Reputation: 106410
You're only ever declaring the result as a Parameter
, and a parent class has no knowledge of what its children have declared (or that would break encapsulation).
If you want to be sure that you always get the right type, then consider passing in the Class
that you want to use in that scenario.
A sample signature would look like this:
public static <T extends Parameter> T init(Class<T> clazz) throws InstantiationException, IllegalAccessException {
return clazz.newInstance();
}
You'll have to do something if either of those methods are thrown, though.
A sample call would look something like this:
// I want a NumberParameter
NumberParameter p = Parameter.init(NumberParameter.class);
Upvotes: 0