我有一个名为Parameter的超类。有许多不同类型的参数,当然它们有不同的方法。问题是我将Parameter初始化为sub之一,但它仍然不允许我使用子类事件!
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();
}
}
}
此方法在Parameter类中静态找到,因此当您可以从传递的字符串中初始化它时。
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!!
}
}
});
现在,参数静态方法必须返回Parameter类的子类,但它仍然不允许我。但现在它是一个子类,那么为什么它不允许我使用它的方法呢?
这就像说你是一个设备,然后我将你子类化为电话,你不能打电话给别人,因为你仍然被称为设备
答案 0 :(得分:2)
Parent
类永远不会知道谁是从它继承的Child
类。如果您在Child
类中定义了一个方法,则只能通过Child
类实例访问/调用它。反之则不然,如果在Parent Class
中定义了一个方法,则所有Child class
实例都可以访问它/调用它。
例如: -
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
}
答案 1 :(得分:0)
您无法使用子类方法,因为在
中Parameter p = Parameter.init((String) box.getSelectedItem());
您将p声明为参数类型。您将只能调用参数中声明的方法。
您可以在事实之后显式地转换创建的子类:
Parameter p = Parameter.init((String) box.getSelectedItem());
NumberParameter np = (NumberParameter)p;
但我认为你正在考虑java继承错误。工厂模式的要点是提供像Parameter这样的接口的不同具体实现。这对于不同子类上的setLabel()方法执行不同的操作非常有用。
答案 2 :(得分:0)
您只是将结果声明为Parameter
,并且父类不知道其子项声明了什么(或者会破坏封装)。
如果您想确保始终获得正确的类型,请考虑传入您希望在该方案中使用的Class
。
示例签名如下所示:
public static <T extends Parameter> T init(Class<T> clazz) throws InstantiationException, IllegalAccessException {
return clazz.newInstance();
}
如果抛出其中任何一种方法,你将不得不做一些事情。
示例调用看起来像这样:
// I want a NumberParameter
NumberParameter p = Parameter.init(NumberParameter.class);