在上一次转换为超类类型之后调用正确的子类方法

时间:2013-07-17 23:04:35

标签: java

假设您有一个基类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类型(或者有没有办法在这里应用泛型?)。我得到一个编译错误(在BC中不存在m())。我假设有一个很好的方法来做到这一点(不必“手动”找出某种方式的真实类型)?

3 个答案:

答案 0 :(得分:2)

为什么不是BC中定义的方法?这就是多态性的全部内容。

您的另一个选择是让对象实现包含m的接口,并具有该接口的集合而不是BC。或者使用反射(ew),或检查类型(ew)。

答案 1 :(得分:0)

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();
    }

}

输出: BCM SC2:M

对于这些场景,您需要在基类中声明方法m。然后你可以覆盖到子类

答案 2 :(得分:0)

此时

BC o = getObj(c);

您有一个对象的引用o。在编译时,你的代码唯一知道的事实是,无论这个引用指向什么(BC,或BC的子类)都有BC中定义的方法。它不能知道你给它的子类是SC1或SC2的一个实例。所以,您的问题是您需要执行仅在子类上定义的方法。你有几个选择。

  1. 反射 - 使用Java的反射功能检查您给出的对象,查看该方法是否可用,然后调用它。但是你丢失了编译时检查,这很慢。不是首选的解决方案
  2. 检查c的实例,强制转换为适当的类型,然后调用方法。这将起作用,但是instanceof也很慢,并且违背了子类化和多态的目的。也不推荐。
  3. 将一个方法(可能是抽象,如果BC永远不需要实例化)引入BC,然后您的子类重写。直接调用此方法。这是更好的解决方案,可能就是你想要的。
  4. 如上所述,但使用您的子类实现的接口,并让您的方法返回该接口。