[英]“class A <T extends SomeClass<T>>” works differently from class B <T extends SomeInterface<T>> ? (Yes)
而定義涉及接口可比性
class B <T extends Comparable<T>>
是眾所周知的且可實例化的,所以在擴展類而不是接口時,相同的用法不能以相同的方式起作用。 這是一個例子
class G <T extends Box<T>> {
T val;
G(T val) {
this.val = val;
}
}
上面的類可以編譯,但是我無法找到實例化G的方法。它似乎需要Box的無限嵌套。
G<Box<Box<..>>>
這是我對Box類的定義
class Box <T> {
T val;
Box(T val) {
this.val = val;
}
}
為了幫助討論,這里有一些類似的例子。 我測試了所有代碼。
下課的意思對我很清楚
class D <T extends Box<String>> {
T val;
D(T val) {
this.val = val;
}
}
我們可以實例化使用
D<Box<String>> d = new D<>( new Box<String> ("hello") );
我們可以對此進行概括,以便Box可以包含任何內容
class F <S, T extends Box<S>> {
T val;
F(T val) {
this.val = val;
}
}
我們可以實例化使用
F<String,Box<String>> f = new F<>( new Box<String> ("hello") );
回到最初的問題,以下是什么意思,以及如何/可以將其實例化?
class G <T extends Box<T>> {
T val;
G(T val) {
this.val = val;
}
}
G類是我對上述D類進行泛化的首次嘗試,以便Box可以容納任何類型,而不僅僅是String。 后來我想到了F類作為解決問題的方法,但我想知道G的含義是什么,為什么它與T extends SomeInterface<T>
時的含義不同。
如果Box
類沒有帶T
構造函數,則可以創建一個擴展Box
的類。 例如:
class NewBox extends Box<NewBox> {
...
}
然后您可以實例化G
:
G<NewBox> g = new G<>(new NewBox());
但在您的情況下,Box具有構造函數Box(T val){...}
,那么NewBox
需要與super
匹配的構造函數,例如:
class NewBox extends Box<NewBox> {
NewBox(NewBox val) {
super(val);
}
}
要實例化它,您應該以null結尾,否則將導致無限嵌套:
G<NewBox> g = new G<>(new NewBox(new NewBox(new NewBox(null))));
更新:回答你原來的問題: G <T extends Box<T>>
意味着T
必須是類型Box
或任何后裔Box
。 正如您正確提到的那樣,它將導致無限嵌套。 但是您仍然可以實例化它, 而無需使用通配符和null
作為類G
的構造函數的參數來創建額外的類 (如上述NewBox
):
G<?> tg = new G<>(null);
如果您擔心類型綁定T extends Box<T>
意味着可以指定為類型參數的唯一類型必須擴展Box
。
該技術用於指定您可以對類型進行的其他操作(例如,眾所周知的Comparable<T>
),因此使用類而不是接口實際上並不常見。
讓我給你舉個例子。 說我們有以下操作
interface Op1<T>{
void doOp1(t: T): T
}
interface Op2<T> {
void doOp2(t: T): T
}
class MyClass implements Op1<MyClass>, Op2<MyClass>{
//By implementing Op1 and Op2 you
//specify that operations doOp1 and doOp2
// can be applied to variable of typr MyClass
}
現在,您要實現通用容器,該容器接受可以將Op1
和Op2
類型的元素應用於
class MyContainer<T extends Op1<T> & Op2<T>>{
//you can apply doOp1 and doOp2 to any variable of the type T
}
MyContainer<MyClass> t = //... Ok
MyContainer<Integer> t = //... Not ok
在函數式編程中,類似(但不是完全相同)的東西稱為類型類
從@Ruslan
和@Some Name
的答案以及@Some Name
問題的評論中得出,這是兩者之間區別的概要
class G <T extends SomeClass<T>>
class B <T extends SomeInterface<T>>
class Enum<E extends Enum<E>>
我發現編寫經過測試的示例會有所幫助。
class G <T extends SomeClass<T>>
G
類要求將T
類型定義如下
class T extends SomeClass<T> {}
這是一個像T
這樣的類的例子
class RussianBox extends Box<RussianBox> {
RussianBox(RussianBox box) {
super(box);
}
}
其中Box
類定義為
class Box <T> {
T value;
Box(T value) {
this.value = value;
}
public String toString() {
return this.getClass().getSimpleName()+" containing {"+this.value+"}";
}
}
這是一個像G
這樣的類的例子
class RussianBoxContainer <T extends Box<T>> {
T value;
RussianBoxContainer(T value) {
this.value = value;
}
public String toString() {
return this.getClass().getSimpleName()+" containing {"+this.value+"}";
}
}
以下代碼實例化了這三個類
Box<String> box = new Box<>("Gold");
out.println("box = " + box );
RussianBox russianBox = new RussianBox( new RussianBox(null) );
out.println("russianBox = " + russianBox );
RussianBoxContainer<RussianBox> containerForARussianBox = new RussianBoxContainer<>(russianBox);
out.println("containerForARussianBox = " + containerForARussianBox );
並產生以下輸出
box = Box containing {Gold}
russianBox = RussianBox containing {RussianBox containing {null}}
containerForARussianBox = RussianBoxContainer containing {RussianBox containing {RussianBox containing {null}}}
class B <T extends SomeInterface<T>>
B
類要求將T
類型定義如下
class T extends SomeClass implements SomeInterface<T> {}
java.lang.Integer
類是T
類的示例
class Integer extends Number implements Comparable<Integer>
因此,當引用接口而不是類時,此模式的行為將有很大不同。
class Enum<E extends Enum<E>>
現在創建一個類似 Enum
的類。 這是一個例子
class RussianBoxContainer2 <T extends RussianBoxContainer2<T>> {
RussianBoxContainer2<T> value;
RussianBoxContainer2(RussianBoxContainer2<T> box) {
this.value = box;
}
public String toString() {
return this.getClass().getSimpleName()+" containing {"+this.value+"}";
}
}
就像Enum
一樣,我們需要先子類RussianBoxContainer2
然后才能使用RussianBoxContainer2
。 這是一個子類的例子
class RussianBox2 extends RussianBoxContainer2<RussianBox2> {
RussianBox2(RussianBox2 box) {
super(box);
}
}
以下代碼實例化了這兩個類
RussianBox2 russianBox2 = new RussianBox2(new RussianBox2(null));
out.println("russianBox2 = " + russianBox2 );
RussianBoxContainer2<RussianBox2> containerForARussianBox2 = new RussianBoxContainer2<>(russianBox2);
out.println("containerForARussianBox2 = " + containerForARussianBox2 );
並產生以下輸出
russianBox2 = RussianBox2 containing {RussianBox2 containing {null}}
containerForARussianBox2 = RussianBoxContainer2 containing {RussianBox2 containing {RussianBox2 containing {null}}}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.