繁体   English   中英

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

[英]Call proper subclass method after previous cast to superclass type

假设您有一个基类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())。 我假设有一个很好的方法来做到这一点(不必“手动”找出某种方式的真实类型)?

为什么不在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:M SC2:M

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

这一点

BC o = getObj(c);

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM