繁体   English   中英

关于Java子类继承返回“this”的方法

[英]Regarding Java subclasses inheriting methods that return “this”

有一个公共方法的类Car

public Car myself() {
  return this;
}

有一个子类Ferrari ,以及一个包含Ferrari对象的变量foo

最后,

Ferrari bar = foo.myself();

这会警告你,因为方法myself()返回一个Car对象,而不是预期的Ferrari

注意:我知道这个例子很愚蠢,因为你只需要做bar = foo 这只是一个例子。


解决方案:

  • 覆盖Ferrarimyself()方法。
  • 分配bar时,将Car对象转换为Ferrari对象。

两种解决方案都有效,我对此感到满意。 但是,当你有几个Car子类时,第一个是不可取的。 我觉得一遍又一遍地覆盖一种方法会破坏继承它的意义。 接下来,关于第二种解决方案,铸造并不漂亮。 感觉很愚蠢 - 如果我的变量属于Ferrari ,那么Java不应该在没有警告我的情况下隐式地施放它吗? 毕竟,Java必须知道返回的对象可以转换为Ferrari ,不是吗?


还有另一种解决方法吗? 只是出于好奇 - 我可以忍受铸造的东西,告诉Java应该是什么东西......

此解决方案以Java库中更常用的方式使用泛型。

它有效,您不必每次都转换结果,也不必在每个子类中覆盖myself方法。

我相信这是唯一不需要覆盖或转换的解决方案。 它确实要求每个子类使用自己的类型作为超类Car的类型参数: class Ferrari extends Car<Ferrari>

class Car<X extends Car<X>> {
    public X myself() {
        return (X) this;
    }
}

class Ferrari extends Car<Ferrari> {
}

然后按预期使用它:

Ferrari testarossa = new Ferrari().myself();

这个概念在Java标准库中也以这种或那种方式使用了几次:

java.lang.Enum

public abstract class Enum<E extends Enum<E>>

java.util.Comparable

public interface Comparable<T>

(当您实现class ShoeSize implements Comparable<ShoeSize>时,您应该传递自己的类类型: class ShoeSize implements Comparable<ShoeSize>

方法链

对此也有很好的用处 - 有一种模式,有些人喜欢,允许方法链接。 这就是StringBuilder作用: new StringBuilder().append("a").append("b").toString() 但是,支持方法链接的类通常很难进行子类化。 使用上面概述的方法可以在这种情况下进行子类化。

这也取决于你如何知道foo变量。

如果你知道的话

Ferrari foo = new Ferrari();

那么一个被覆盖的方法就像

class Ferrari extends Car {
    @Override
    public Ferrari myself() { 
        return this;
    }
}

将允许你利用covaraince,你可以做到

Ferrari foo = new Ferrari();
Ferrari bar = foo.myself();

虽然可能没有多少应用案例这是有道理的:当你已经知道它是法拉利时,你可以写

Ferrari bar = foo;

当你只知道它时,情况就不同了

Car foo = new Ferrari();

然后你运气不好:你不再知道运行时类型,无论如何你都要投。

(注意:当涉及到自引用泛型类型时,这种重写方法以更具体的类型返回this有一个真实的应用案例。这有时被称为getThis技巧

关于你的陈述

感觉很愚蠢 - 如果我的变量属于法拉利,那么Java不应该在没有警告我的情况下隐式地施放它吗? 毕竟,Java必须知道返回的对象可以转换为法拉利,不是吗?

这不是真的。 没有人阻止你覆盖像这样的方法

class Ferrari extends Car {
    @Override
    public Car myself() { 
        return new Volkswagen(); 
    }
}

然后演员阵容将不再有效

子类可以覆盖基类方法,并且作为该合同的一部分表明它将返回特定类型。 这为类的用户提供了清晰度,而期望用户知道返回的类型并相应地投射它不会。 因此,覆盖更好。

暂无
暂无

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

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