簡體   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