2010-10-27 356 views
24

當從子類對象調用此方法時,是否有任何優雅的方法可以使Java方法位於子類的父類返回對​​象中?如何讓Java父類方法返回子類的對象

我想在不使用其他接口和額外方法的情況下實現此功能,並且不使用類轉換,輔助參數等等。

更新:

對不起,我是不太清楚。我想要實現方法鏈,但我有父類方法的問題:當我調用父類方法時,我失去對子類方法的訪問... 我想我已經提出了我的核心理念。

所以方法應該返回this對象this.getClass()類。

回答

46

如果你只是在尋找方法鏈接對定義的子類,那麼下面應該工作:

public class Parent<T> { 

    public T example() { 
    System.out.println(this.getClass().getCanonicalName()); 
    return (T)this; 
    } 
} 

如果你喜歡,那麼指定通用返回類型的一些子對象可能是抽象的(這意味着你不能從ChildA訪問childBMethod):

public class ChildA extends Parent<ChildA> { 

    public ChildA childAMethod() { 
    System.out.println(this.getClass().getCanonicalName()); 
    return this; 
    } 
} 

public class ChildB extends Parent<ChildB> { 

    public ChildB childBMethod() { 
    return this; 
    } 
} 

,然後你使用這樣

public class Main { 

    public static void main(String[] args) { 
    ChildA childA = new ChildA(); 
    ChildB childB = new ChildB(); 

    childA.example().childAMethod().example(); 
    childB.example().childBMethod().example(); 
    } 
} 

輸出將是

org.example.inheritance.ChildA 
org.example.inheritance.ChildA 
org.example.inheritance.ChildA 
org.example.inheritance.ChildB 
org.example.inheritance.ChildB 
+0

非常感謝。這正是我想要的。 – 2010-10-27 13:16:26

+0

@Errandir沒問題 - 很高興幫助 – 2010-10-27 13:17:22

+1

完美。但是我需要將'@SuppressWarnings(「unchecked」)'添加到'example()'中。 – 2012-10-01 02:52:10

1

我確切地知道你的意思,在Perl中有$class變量,這意味着如果你在子類上調用一些工廠方法,即使它沒有在子類中重寫,如果它實例化任何$class實例子類將被創建。

Smalltalk,Objective-C,許多其他語言都有類似的功能。

唉,在Java中沒有這樣的等效工具。

+0

在Perl中,根本不存在通用的內置'$ class'變量。它可以通過檢索類方法的第一個參數(例如,MyClass-> mySub()調用作爲第一個參數傳遞MyClass)或者通過獲取object(這是調用對象的方法的第一個參數,例如'$ myclass_object-> mySub()'調用將'$ myclass_object'作爲第一個參數,'ref($ myclass_object)'返回'「MyClass」') 。請知道你在說什麼。 – DVK 2010-10-27 10:08:01

+0

但是,正如你所說,類方法的第一個參數始終是該方法應用於的類的名稱。這意味着您可以編寫方法,然後執行'$ class-> newInstance()',如果在子類上調用該方法,將會創建子類的實例。用於工廠方法,施工中的模板方法模式等等。在Java中,即使調用MySubObj.newInstance(),靜態MyObj newInstance(){..}也將總是生成一個MyObj,並且沒有任何方法可以解決這個問題。在Perl中。 – 2010-10-27 12:14:23

3

只需證明:

public Animal myMethod(){ 
    if(this isinstanceof Animal){ 
    return new Animal(); 
    } 
    else{ 

    return this.getClass().newInstance(); 
    } 
} 
+0

隨着子類的添加,更改和刪除,此方法必須一次又一次地更改。儘管如此,仍然是一個解決方案。 – BoltClock 2010-10-27 09:58:32

+0

@BoltClock,剛剛證明,我已經解決了您在此更新中的問題。 – 2010-10-27 10:02:49

2

您可以撥打this.getClass()獲得運行時類。

但是,這不一定是調用該方法的類(它可能會更進一步向下)。

而且您需要使用反射來創建新的實例,這很棘手,因爲您不知道子類具有哪種類型的構造函數。

return this.getClass().newInstance(); // sometimes works 
+0

聽起來像:父母可以通過反思產生一個孩子,但不能保證是他的。 :) – 2010-10-27 10:35:15

+0

它將成爲當前類的一個子類,因爲「this」總是。不過,它可能是一個間接的子類。 – Thilo 2010-10-28 01:12:19

0
public class Parent { 
    public Parent myMethod(){ 
     return this; 
    } 
} 
public class Child extends Parent {} 

並調用它像

 Parent c = (new Child()).myMethod(); 
     System.out.println(c.getClass()); 

這個解決辦法是正確的?如果是,那麼它與第一種解決方案有什麼不同?

7

你想達到什麼目的?這聽起來像個不好的主意。家長不應該對其子女有任何瞭解。看起來非常接近打破Liskov Substitution Principle。我的感覺是,通過改變總體設計可以更好地服務您的用例,但是如果沒有更多信息,很難說。

抱歉聽​​起來有點迂腐,但是當我看到這樣的問題時,我有點害怕。