2017-02-18 39 views
4

我儘可能地使我的代碼儘可能通用,以嘗試和幫助未來的人。我的抽象類有一個類型類的方法和一個類型類的輸入。在擴展抽象的類中,我試圖實現該方法無濟於事。我究竟做錯了什麼?在Java的子類中實現抽象方法

public abstract class A { 
    public abstract A method1(A arg); 
} 

public class B extends A { 
    @Override 
    public B method1(B arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method 
} 
+3

參數必須是「A」型。 –

+0

該方法的參數是否必須與子類(在您的示例'B')中具有相同的確切類型? –

+0

是的。 B.method1中只有在B中需要的方法。 –

回答

3

達到你想要的一切:參數的類型來聲明類相關聯,您可以使用泛型。

抽象類:

public abstract class A <T extends A<T>> { 
    public abstract T method1(T arg); 
} 

具體類:

public class B extends A<B> { 
    @Override 
    public B method1(B arg) { 
    ... 
     return ... 
    } 
} 
+1

這會產生警告,因爲'A'是通用的,在'''A'不是。你應該修正它如下:'>' –

+1

@Federico Peralta Schaffner確實,謝謝:) – davidxxx

0

A.method1合同意味着每個對象,它是一個A必須具有method1可採取任何A對象。

B.method1的情況下,它可能需要B對象,但它不能接受另一個A

0

除了overidden方法參數類型,你寫的每一件事都是正確的,你不能在子類中改變超類抽象方法的簽名。

public abstract class A { 
    public abstract A method1(A arg); 
} 

public class B extends A { 
    @Override 
    public B method1(A arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method 
} 
+0

對不起@AndyTurner我寫了返回類型而不是參數類型。謝謝你糾正我。 –

2

應保留參數的類型和編號。返回類型,如果它是原始類型,應保持相同,但如果它是引用類型,則它可以是子類型。

你的情況,這個變化對public B method1(B arg) { "...insert code here"}public B method1(A arg) { "...insert code here"}

2

想想Liskov substitution principle:爲了從一個超類沒有區別,子類必須接受所有相同參數的超類將;並返回超類可能

另一種方式把這是一個子類方法可以:

  • 返回更特定類型的超類方法(因爲這是一個值,超可能返回);例如,如果超類返回Object,則子類可以返回String,因爲所有String都是Object s。

    這就是所謂的協變返回類型,並在Java中是允許的。子類不僅可以返回更具體的返回類型,還可以拋出比超類更多的特定檢查異常;但他們也可以而不是聲明它們拋出超類方法拋出的檢查異常。

  • 接受比超類方法更通用的類型(因爲這允許子類接受超類將會使用的所有參數)。

    這將被稱爲逆變參數類型;但在Java中允許使用而不是。原因是在Java中選擇重載的方式:不幸的是,方法簽名(包括參數類型,但不包括返回類型)必須是相同的

語言規範的相關部分是JLS Sec 8.4.8.3

您的問題是使參數類型B:這是比A具體,所以B一個實例是不可替代爲A一個實例,因爲A.method1接受一個參數A,而B.method1沒有。

品牌B.method1採用A型號的參數。

相關問題