假设您有一个基类BC,其中包含子类SC1、SC2。。。以及对象的集合C(一些是SC1类型,一些是SC2类型,…)。方法m在子类中定义,而不是在BC中。我希望做这样的事情:
class AnotherClass {
private BC getObj(Container c) { /*return something from c*/ }
private void anotherMethod() {
...
BC o = getObj(c);
o.m();
}
}
现在getObj将返回一个对对象的引用o,据我所知,它必须是BC类型(或者有没有方法在这里应用泛型?)。我得到了一个编译错误(m()在BC中不存在)。我想有一种很好的方法可以做到这一点(而不必以某种方式"手动"计算出o的真实类型)?
为什么BC
中没有定义方法?这就是多态性的意义所在。
您的另一个选择是让对象实现一个包含m
的接口,并拥有该接口的集合而不是BC
。或者使用反射(ew),或者检查类型(ew)。
public class BC
{
protected void m()
{
System.out.println("BC:M");
}
}
public class SC1 extends BC
{
public void m()
{
super.m();
System.out.println("SC1:M");
}
}
public class SC2 extends BC
{
public void m()
{
super.m();
System.out.println("SC2:M");
}
}
public class TestClass
{
public static void main(String args[])
{
SC1 sc1_one= new SC1();
SC1 sc1_two= new SC1();
SC2 sc2_one= new SC2();
SC2 sc2_two= new SC2();
ArrayList al = new ArrayList<BC>();
al.add(sc1_one);
al.add(sc2_one);
al.add(sc1_two);
al.add(sc2_two);
BC bc = (BC) al.get(3);
bc.m();
}
}
输出:BC:MSC2:M
对于这些场景,您需要在基类中声明方法m。然后您可以覆盖到子类
此时
BC o = getObj(c);
你有一个对象的引用。在编译时,您的代码唯一知道的事实是,无论这个引用指向什么(BC,或BC的子类),都有在BC中定义的方法。它不知道你给它的子类是SC1或SC2的实例。因此,您的问题是需要执行仅在子类上定义的方法。这里有几个选项。
- 反射-使用Java的反射功能来检查给定的对象,看看该方法是否可用,然后调用它。但您会失去编译时的检查,而且速度很慢。不是首选解决方案
- 检查c的实例,转换为适当的类型,然后调用这些方法。这将起作用,但instanceof也很慢,并且无法实现子类化和多态性的目的。也不推荐
- 在BC中引入一个方法(如果BC从不需要实例化,则可能是抽象的),然后子类覆盖该方法。直接调用此方法。这是一个更好的解决方案,可能也是你应该追求的
- 如上所述,但是使用子类实现的接口,并让方法返回该接口