首頁 >Java >java教程 >如何在 Java 中使用類型變數引用目前型別?

如何在 Java 中使用類型變數引用目前型別?

DDD
DDD原創
2024-12-24 21:53:14425瀏覽

How Can I Refer to the Current Type Using a Type Variable in Java?

如何用型別變數引用目前型別

你能用型別變數引用目前型別嗎?

假設你是建立一個函數以傳回目前類型的實例。有沒有辦法讓類型變數 T 引用精確的子類型(因此 T 應該引用 B 類別中的 B)?

class A {
    <T extends A> void foo();
}

class B extends A {
    @Override
    T foo();
}

解決方案

為了建立 StriplingWarrior 的回應,需要以下設計(分層流暢建構器 API的公式):

首先,一個抽象基類(或介面),用於建立用於檢索擴展類的實例的運行時類型的契約:

/**
 * @param <SELF> The runtime type of the implementer.
 */
abstract class SelfTyped<SELF extends SelfTyped<SELF>> {

   /**
    * @return This instance.
    */
   abstract SELF self();
}

中間擴展類必須是抽象的並維護遞歸類型參數SELF:

public abstract class MyBaseClass<SELF extends MyBaseClass<SELF>>
extends SelfTyped<SELF> {

    MyBaseClass() { }

    public SELF baseMethod() {

        //logic

        return self();
    }
}

進一步派生的類別可以遵循相同的圖案。但是,如果不使用原始類型或通配符(這會破壞該模式的目的),這些類別都不能直接用作變數類型。例如(如果 MyClass 不是抽象的):

//wrong: raw type warning
MyBaseClass mbc = new MyBaseClass().baseMethod();

//wrong: type argument is not within the bounds of SELF
MyBaseClass<MyBaseClass> mbc2 = new MyBaseClass<MyBaseClass>().baseMethod();

//wrong: no way to correctly declare the type, as its parameter is recursive!
MyBaseClass<MyBaseClass<MyBaseClass>> mbc3 =
        new MyBaseClass<MyBaseClass<MyBaseClass>>().baseMethod();

這就是為什麼這些類別被稱為“中間類別”,以及為什麼它們都應該被聲明為抽象的。 「葉」類別需要完成循環並使用該模式,該模式解析繼承的類型參數 SELF 及其類型並實作 self()。為了防止破壞契約,它們也應該被標記為final:

public final class MyLeafClass extends MyBaseClass<MyLeafClass> {

    @Override
    MyLeafClass self() {
        return this;
    }

    public MyLeafClass leafMethod() {

        //logic

        return self(); //could also just return this
    }
}

使用這樣的類別使得模式可用:

MyLeafClass mlc = new MyLeafClass().baseMethod().leafMethod();
AnotherLeafClass alc = new AnotherLeafClass().baseMethod().anotherLeafMethod();

這樣做的主要優點是方法呼叫可以在類別層次結構中上下鏈接,同時保持相同的特定返回類型。

以上是如何在 Java 中使用類型變數引用目前型別?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn