【问题标题】:Incorrect versions of methods called with java inheritance and interface [duplicate]使用java继承和接口调用的方法版本不正确[重复]
【发布时间】:2013-03-10 08:24:05
【问题描述】:

我有一个简单的继承层次结构和一个单一的接口。考虑将由 B 类扩展的 A 类。我希望这两个类都实现接口 I 并且 A 类是抽象的。在java中我大致有以下内容:

public interface I {
    public double foobar();
    public void print();
}

public abstract class A implements I {
    @Override public double foobar() { /*return foo*/}
    @Override public void print() {
        System.out.print(foobar());   
    }
}

public class B extends A {
    @Override public double foobar() { /*return bar*/ }
    @Override public void print() {
        super.print();
        System.out.print(foobar);
    }
}

我的意图是,当我实例化 B 类型的对象并调用它的 print() 时,让 B 类型的对象首先打印 A 类的 foo,然后打印 B 类的 bar;但是,当我编译执行此代码时,它在两种情况下都从 B 类调用 foobar()。例如,如果 foo 等于 1,bar 等于 2,则上述代码的输出如下:

2 2

但我希望它是 1 2

我尝试使用各种类型转换调用该方法,但没有运气。有什么建议吗?

编辑:感谢您的许多建议,只是为了澄清一下,我希望 A 的每个潜在子类都实现 I 并且我为没有明确说明而道歉。此外,我目前通过在 A privateFooBar() 中添加一个由 A 的 print 和 A 的 foobar 调用的附加方法来获得工作代码;但是,我仍然想知道是否有更优雅的方法来完成这项任务。

【问题讨论】:

  • 你的电话号码在哪里?
  • 很抱歉没有明确地编写我的调用代码。当我说“当我实例化 B 类型的对象并调用它的 print()”时,我的意思是 public class X { public static void main(String[] args) { B b = new B(); B.print(); }}

标签: java inheritance interface


【解决方案1】:

foobar() 在 B 类中被覆盖。因此,每次在 B 类的实例上调用它时,都会调用该方法的 B 类版本。这就是多态性的全部意义所在。

如果您希望 A 中的 foobar() 方法始终返回 A 的 foobar 版本,并且不希望子类中的方法更改它,则应在 A 中将 foobar() 设为 final

或者您可以委托给 A 中的 private 方法:

public abstract class A implements I {
    @Override 
    public double foobar() { 
        return privateFoobar();
    }

    private double privateFoobar() {
        /* return foo */
    }

    @Override public void print() {
        System.out.print(privateFoobar());   
    }
}

public class B extends A {
    @Override public double foobar() { /*return bar*/ }
    @Override public void print() {
        super.print();
        System.out.print(foobar());
    }
}

【讨论】:

  • 我选择了私有方法选项,但我很好奇如果我将 A 的 foobar() 更改为 final,是否必须更改子类 B 中的任何内容?为了提供上下文,我有一个代表运输公司的类,方法 foobar() 代表一个 CalculateCost() 方法,该方法返回发送相关包裹的成本的两倍。 A 类表示一个抽象方法,并具有 CalculateCost() 返回权重 * cost_per_weight。子类 B 的 CalculateCost() 返回父类的 CalculateCost() 添加到表示附加费的双精度。我想知道是否有更好的方法
  • 如果 A.foobar() 是私有的,你不能在 B 中覆盖它。这就是 final (on methods) 的意思。
  • 通过“私有方法选项”我并不是说将 A.foobar() 设为私有,而是按照上述帖子中的建议制作另一个私有类 privateFoobar。
  • 抱歉,我的意思是“如果 A.foobar() 是 final”。
  • 感谢您的澄清。最后的想法是对上述帖子的回应。
【解决方案2】:

在您的 A 类中,您正在调用 foobar(),它在 B 类中被覆盖

public abstract class A implements I {
    @Override public double foobar() { /*return foo*/}
    @Override public void print() {
        System.out.print(foobar()); // HERE 
    }
}

您可以将方法设为最终方法或私有方法

【讨论】:

  • 5 分钟前刚刚说过 :)
  • 发帖前忘记刷新页面
  • 而且您不能将其设为私有。它必须保持公开状态才能遵守基类合同。
【解决方案3】:

这是一个关于 foobar 的方法。您可以从 B 调用 super.foobar(),并调整覆盖的 print() 方法。 final 或 private 将不起作用,因为那样您就无法覆盖该方法。代码如下:

PS:我将返回类型更改为 String 以返回 "foo" 和 "bar" :)

public class P4  {
    public static void main (String[] args) {
    new B().print();
    System.out.println();
}}

interface I {
    public String foobar();
    public void print();
}

abstract class A implements I {
    @Override public String foobar() { return "foo";}
    @Override public void print() {
        System.out.print(foobar());   
    }
}

class B extends A {
    @Override public String foobar() { return "bar"; }
    @Override public void print() {
        System.out.print(super.foobar());
        super.print();
    }
}

【讨论】:

  • 我考虑过这个选项,但在我的原始代码中,父级的打印位于大量文本的中间,需要我基本上重写父级的打印代码
  • 无论如何你都在覆盖 print(),所以不要调用会调用 this.foobar() 的 auper.print(),只需调用 this.foobar()。没错,这意味着复制粘贴 super.print() 的大部分内容,但我相信你已经考虑过了。基本上,在 print() 中你有“foo”和“bar”,只需要为应用程序格式化它。问候, - M.
【解决方案4】:

As Class B 重写 Class A 的 foobar 方法 Class B 总是调用 Class B 版本的 foobar。

如果你想让 Class B 改变 so print 的方法行为,它会在不调用 super.print() 的情况下打印 foo 和 bar 的值。

在 B 类中为 bar 定义新方法,而不是 A 类的 Overriding 方法。

public class B extends A {
    public double bar() { /*return bar*/ }
    @Override public void print() {
        System.out.print(bar());
        System.out.print(foobar());
    }
}

当您更改 print() 方法时,重写 print() 而不是 foobar() 方法是正确的。

【讨论】:

  • 我也考虑过这个选项,但我对我的导师选择的措辞不佳感到困惑,因为这是一个作业。他要求 A 的每个子类都实现 I;但是,我的理解是编写 public class B extends A implements I 是多余的。很抱歉没有明确说明 A 的每个子类都应该实现 I
猜你喜欢
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 1970-01-01
相关资源
最近更新 更多