【问题标题】:Can a Parent call Child Class methods?父母可以调用子类方法吗?
【发布时间】:2009-09-07 01:22:23
【问题描述】:

参考here

A 是一个预编译的 Java 类(我也有源文件) B 是我正在创作的 Java 类
B 扩展 A。

如何实现逻辑以使 A 可以调用 B 拥有的方法。
以下是条件:

  • 我不想碰 A(仅作为 最后一个选项,如果没有 存在其他解决方案)。
  • 我不想使用反射。

如上所述,如果需要,我可以修改 A. 无论哪种方式,可能的解决方案是什么?

【问题讨论】:

    标签: java inheritance


    【解决方案1】:

    Class A 应该定义它要调用的方法(可能是抽象的,A 应该是一个抽象类,根据 Paul Haahr 的优秀 guide); B 可以(实际上必须是具体的,如果方法是抽象的)覆盖这些方法。现在,从 A 中的其他方法调用这些方法,当发生在 B 类的实例中时,转到 B 的覆盖。

    整体设计模式被称为Template Method;要覆盖的方法通常称为“挂钩方法”,执行调用的方法称为“组织方法”。

    【讨论】:

    • @Alex Class A 是某种库类,它不是抽象的。要使用我正在扩展 A 的库。在这种情况下我该怎么办?
    • @unknown,很高兴你喜欢它!-)
    • @Kevin,如果它是一个库类,那么它就无法明智地了解应用程序级类——这是依赖箭头的错误方向!查找依赖反转:创建一个接口(依赖于接口等抽象事物非常好)并让您的应用程序类实现它,使用依赖注入为库类实例提供它需要调用的接口实现。顺便说一句,如果库提供了具体的类但需要你扩展它们,那么它的设计是可疑的:将 Haahr 的文章发送给库的架构师!-)
    • @Alex:我理解第一部分是B实现接口I,什么是依赖注入?那么A不需要持有I的引用来调用B的方法吗?我应该在 A 类中插入一个字段私有接口 I 吗?
    • 依赖注入(搜索它!)可以通过多种方式实现(有自动化它的框架和许多手动方法),但它确实归结为 A 持有对 I 接口的私有引用(否则,它会在哪里调用我的方法?-)。由于您热衷于让 B(它扩展 A)实现 I(打破设计模式前两个原则:程序到接口,而不是实现;更喜欢组合而不是继承),要么让 A 在其构造函数中接受 I,而 B调用,或 setTheI 设置器(B 的构造函数可以使用 this 作为参数调用)。
    【解决方案2】:

    是的,如果您重写超类/基类的函数,那么对这些函数的调用in 基类将转到子类/派生类。在我看来,这似乎是一个糟糕的设计,但你去吧。

    class Base
    {
        public void foo()
        {
            doStuff();
        }
        public void doStuff()
        {
            print("base");
        }
    }
    
    class Derived extends Base
    {
        @Override
        public void doStuff()
        {
            print("derived");
        }
    }
    
    new Derived().foo(); // Prints "derived".
    

    显然Derived 的所有方法都必须已经在Base 中定义,但否则(没有自省)在逻辑上是不可能的。

    【讨论】:

    • Google 已经在 AsyncTask 中实现了这个精确的结构,基类作为抽象。我无法理解它的糟糕设计
    • 我不记得我的确切想法,但我想我在哀叹 Java 中的所有方法默认情况下都是虚拟的。在 C++ 中,您必须声明可以在派生类中重写方法(而在 Java 中,您必须使用 final 显式阻止它)。也许吧。
    • “似乎是一个糟糕的设计” - 对我来说似乎是明智的默认行为:通常你会覆盖一个方法,因为你想要你的覆盖版本叫做。 (不确定基类是否有办法显式调用自己的方法,而不是从子类中覆盖任何方法。)
    • 这不能回答问题。基 -> 父,派生 -> 子。问题是,“父类可以调用子类方法吗?”。您已经展示了子类可以调用父方法。
    • 不,我没有... Base.foo 显然调用了Derived.doStuff
    【解决方案3】:

    我会很犹豫这样做。如果我错了,请纠正我,然后我会删除,但听起来你想维护一个 A 对象和一个 B 对象。如果它们确实不是同一个对象,那么您必须做的“捆绑在一起”(这是一个科学术语)将非常难看。

    【讨论】:

    • 对不起,我没听懂这个问题,你能改一下吗?
    • @kevin-Boyd 请检查 Alex-Martelli 对他的回答的第二条评论(长评论)。他指出了我想说的同一件事。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 2016-02-14
    相关资源
    最近更新 更多