【问题标题】:Method return value depending on implementation type方法返回值取决于实现类型
【发布时间】:2015-05-19 09:56:04
【问题描述】:

我有一个具有以下结构的程序

  • abstract class A
  • class B extends A
  • class C extends A

所以class A 有两种不同的实现方式。

现在我在abstract class A 中有一个通用方法

protected ReturnType doStuff() {
    //THe Return Type is the Problem
}

如果我在class B 中使用此方法,我希望它返回class B 的对象 和class C中的相同

问题:如何将 ReturnType 设置为 B 或 C? 仿制药是正确的方法吗?我试过了,但感觉不对,因为它们都是 A 的亚型。 或者我应该返回“A级”并相应地进行转换?那也感觉不对

【问题讨论】:

  • 只需将返回类型设置为Object
  • @AkashRajbanshi - 不!引入泛型是为了完全防止你想说的话
  • 是的..泛型是最好的 :D @TheLostMind

标签: java


【解决方案1】:

您可以执行以下操作

abstract class A<RT extends A> {
    protected abstract RT doStuff();
}

class B extends A<B> {
    // doStuff must return a B
}

class C extends A<C> {
    // doStuff must return a C
}

【讨论】:

  • 我在想 - 返回A会不会更好。任何方法调用都将委托给适当的对象(BC)对吗?
  • @TheLostMind 特别是对于构建者来说,了解实际的返回类型通常很有用。 BC 可能有其他方法不在 A 上。
  • @chrylis 但是那有什么意义呢?如果您持有一个(静态)类型B 的变量,那么您无论如何都知道确切的类型。您知道,在使用继承方法时,您也会通过调用B.doStuff() 获得B。我的意思是,为什么声明 A&lt;B&gt; 类型的变量比声明 B 类型的变量“更好”。
  • @chrylis - 哦。所以,如果有必要知道类型/具体类,那么这种方法就是要走的路。谢谢:)
  • 不应该是abstract class A&lt;RT extends A&lt;RT&gt;&gt;吗?或者您想使用extends A 中的A 作为原始类型?但我想,这无关紧要。这是F-bounded polymorphism 的另一个示例。
【解决方案2】:

Java 支持方法返回类型的协变。

您可以将抽象方法声明为:

protected abstract A doStuff();

并且返回扩展A的东西没有问题:

protected B doStuff() { ... }
protected C doStuff() { ... }

这是完全安全的,因为如果调用:

A a = new B();
A res = a.doStuff();

B 扩展了A,因此使用“常规”A 和协变类型可以做的所有事情都没有问题。

【讨论】:

  • 使用这种方法我需要在class Bclass C 中实现doStuff() 吗?这是我要避免的,因为它的作用完全相同,只是返回预期的类型
  • @Dude 你不会有太多选择,因为B.doStuff()C.doStuff() 首先返回一个不同类型的对象,你必须同时实现它们,或者在最起码实现一些其他protected abstract 方法,它返回的对象不同,并从A.doStuff() 调用它。
【解决方案3】:

你可以这样做。

A result = doSomeStuff();

这将返回 A 但它将是它被调用的类的一个实例。 A 类将返回原始类。如果您在抽象类中调用另一个被超类覆盖的方法。将调用被覆盖的方法,而不是抽象类中的方法。当然,如果您愿意,您也可以将其转换为实例类型。

如果不想检查类型可以使用反射...

protected A doSomeStuff()
{
    A a = null;
    try
    {
        a = this.getClass().getConstructor().newInstance();
    }
    catch (InstantiationException | IllegalAccessException | IllegalArgumentException
            | InvocationTargetException | NoSuchMethodException | SecurityException e)
    {
        e.printStackTrace();
    }

    return a;
}

/*
protected A doSomeStuff()
{
    if (this instanceof B)
    {
        return new B();
    }
    else if (this instanceof C)
    {
        return new C();
    }

    return null;
}
*/

【讨论】:

  • 我不想使用硬编码的 if else 构造,因为将来会有更多此类的实现,我不想每次都更改此代码部分,但感谢您的努力跨度>
  • 您可能想阅读以下内容:Why not use instanceof operator in OOP design?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-29
  • 2019-02-10
  • 2023-01-11
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 2011-06-22
相关资源
最近更新 更多