2017-04-10 89 views
4

我有兩個類擴展了一個公共基類。基類有一個代碼,對於一個具體的子類,需要知道另一個具體子類的Class。因此,如果FooBar延伸爲Base,則Foo的實例需要知道Bar.class,並且Bar的實例需要知道Foo.class返回類<T>從方法

而且,我很傻,我正在嘗試做正確的事情,並使用Java泛型來確保子類返回一個有效的Java類對象,它擴展了基類。

所以,我嘗試這樣做:

class Base { 
    abstract protected <T extends Base> Class<T> getOtherClass(); 
} 

編譯器似乎與建設相當快樂。問題出現在實現中。

首先,我想:

class Foo extends Base { 
    @Override 
    protected <T extends Base> Class<T> getOtherClass() { 
    return Bar.class; 
    } 
} 

(其中Bar也延伸Base

這抱怨說我在返回值的類型不匹配,這需要一個演員。

然後,我想:

class Foo extends Base { 
    @Override 
    protected Class<Bar> getOtherClass() { 
    return Bar.class; 
    } 
} 

現在,編譯器會抱怨需要鑄造在Class<Bar>

然後我嘗試:

class Foo extends Base { 
    @Override 
    protected Class<Base> getOtherClass() { 
    return Bar.class; 
    } 
} 

現在,我得到投訴:需要在Class<Base>在返回值的演員。

有沒有一種表達方式避免任何強制轉換?

回答

6
abstract class Base<T extends Base> { 
    abstract Class<T> getOtherClass(); 
} 
class Foo extends Base<Bar> { 
    @Override Class<Bar> getOtherClass() { return Bar.class; } 
} 

......或者......

abstract class Base { 
    abstract Class<? extends Base> getOtherClass(); 
} 
class Foo extends Base { 
    @Override Class<Bar> getOtherClass() { return Bar.class; } 
} 
+0

第二個是比較什麼,我釣 - 我會在幾分鐘內接受這一點。出於好奇,你知道爲什麼'''工作和'T'(就像我在問題中使用的那樣)不是?謝謝! – CommonsWare

+3

當您編寫' Class getOtherClass()'時,您告訴編譯器您的方法調用者可以編寫'Class clazz = myFoo.getOtherClass()'。你在說_caller_可以選擇一個「Base」的子類型。這不是你的方法實現所說的。 '?擴展Bar'意味着_implementation_選擇一個子類型並且調用者不知道它是什麼。 (也就是說,我認爲如果你選擇選項2,當你發現自己被迫陷入尷尬的陣容時,你會發現自己已經選擇了希望選擇選項1的選項。) –

+0

啊!好的,這是有道理的。再次感謝!就方案1而言,對於這種特殊情況,我有理由相信方案2將起作用。這是一個用於測試Android O行爲更改的非常簡單的示例應用程序。我實際上並沒有使用'Class' - 我只是將它傳遞給Android(顯式的'Intent'構造函數)。偶爾,我會嘗試推動我對泛型更精細的理解的界限。 :-) – CommonsWare