【问题标题】:How to use inheritance correctly and avoid downcasting如何正确使用继承并避免向下转换
【发布时间】:2015-07-21 01:41:50
【问题描述】:

让我们建立一个假设场景。我有父类

public class A {
    protected void doSomething(){
        //do something the A way
    } 
}

还有子类

public class B extends A{
    @Override
    protected void doSomething(){
        // do something the B way
    } 
}

我有一些假设的课程:

public class SomeClass implements someInterface{
    @Override
    public void someMethod(A aObject){
        aObject.doSomething();
    } 
}

但我想使用 B 的行为,我无法更改方法参数,也无法将其向下转换为 B。

显然我正在处理一个更大的问题,但这是相同的原则,我自己的答案是将 A 的属性克隆到 B 中,然后使用 B。但在此之前我想听听更多意见。

编辑:约束,我不能将 B 的实例传递给方法,也不能使用 instanceof 方法。

编辑 2:我从未收到 B 的实例,因为 someClass 从必须始终使用 A 实例的接口覆盖此方法。

编辑 3:这是由我遇到的设计不佳的遗留代码产生的情况,我只是想找出更快但更干净的方法来修复作为练习。

【问题讨论】:

  • 如果参数Ainstanceof B,将使用BdoSomething()方法,因为它是OverridingAdoSomething()方法。无需将 A 转换为 B 即可使其正常工作。
  • “我从来没有收到 B 的实例,因为 someClass 从必须始终使用 A 实例的接口覆盖了这个方法。”你怎么能确定你永远不会收到 B 的实例(因为 B is-a A)?我信任的唯一约束是someInterface 中描述的约束。
  • 你有可能重构 A 和/或 B 吗?

标签: java oop


【解决方案1】:

只需将B 的实例传递给someMethod(),因为B "ISA" A,它会工作并调用BdoSomething()

【讨论】:

  • 约束:我从未收到 B 的实例
  • 那你的设计错了。如果您想在A(而不是子类B)上调用BdoSomething(),那么该代码属于A(或某些实用程序包)。
  • 同意,好事是代码不是我的,坏事是我必须处理它。谢谢约翰。
【解决方案2】:

简单的答案是这是不可能的。

当您创建superclass 的对象时,它没有subclass 的方法。因此,根本不可能在superclass 对象上调用subclass 方法。

【讨论】:

    【解决方案3】:

    要使用 B 类的方法,您传入的对象必须是 B 类的实例。然后,当您执行 aObject.doSomething() 时,将自动调用 B 类的方法,因为在运行时 A 对象将被标识为 B 对象,该对象实际上覆盖了 doSomething() 方法。

    【讨论】:

    • 约束:我从未收到 B 的实例
    • @LuisDurazo 如果您没有 B 的实例,我看不出如何从对象上的 B 类调用方法,除非该方法是静态的并且您正在传递它作为参数。 B 是 A,但 A 不是 B。它不是双向的。因此,如果您收到 A 的实例,除非您能够强制转换它,否则您不能将其视为 B。
    • 这正是问题所在,真的没有办法吗?我不能克隆 A 以适应 B 并将 B 的所有其他属性都归零吗?
    • @LuisDurazo 据我所知,这是不可能的,除非你为它设置了某种结构。即 B 有一个构造函数,它接受 A 的一个实例,然后你构造一个 B 的新实例并传入 A,然后调用它的方法。
    • 我同意,它实际上是 A 的 800 行对象,B 也是几百行的对象,到处都是代码气味,特别是该方法首先不应该存在。哦,好吧,遗留代码。
    【解决方案4】:

    另一个答案是,这完全倒退到考虑继承和不同类调用方法的正确方法。

    为了让B扩展A,B需要是A的一个特例。我们可以在passengerAuto/vehicle,或者circle/shape等之间建立这样的关系。

    您似乎试图在一个类中创建一个方法,然后围绕它创建一个继承关系,以便您可以在两个地方使用该方法。但是有很多地方可以放置可以从多个地方调用的方法,这是一个非常糟糕的地方。

    不要这样做。不要设计你的类,以便你可以进行“漂亮”的方法调用。 OO 编程相当于“来,拿着我的啤酒,看这个”。

    【讨论】:

    • 我同意这是设计不佳的,我将不得不重构其中的大部分(这是我没有编写的遗留代码),谢谢 arcy。
    猜你喜欢
    • 2019-02-04
    • 2018-01-18
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2016-12-13
    • 1970-01-01
    相关资源
    最近更新 更多