如何在超类中使用子类方法?

时间:2015-07-05 16:31:28

标签: java inheritance methods casting return-value

我有一个名为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类的子类,但它仍然不允许我。但现在它是一个子类,那么为什么它不允许我使用它的方法呢?

这就像说你是一个设备,然后我将你子类化为电话,你不能打电话给别人,因为你仍然被称为设备

3 个答案:

答案 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);