[英]Abstract Classes inheriting abstract methods with differing parameter type
想象一下,我有一個帶有方法的抽象類Animal:
public abstract void fetch(Animal ani);
然后,我有一個使用以下內容擴展此抽象類的類:
public class GoldenRetriever extends Animal {
public void fetch(GoldenRetriever pup) {
pup.paws = "I have paws";
}
}
我希望每個擴展Animal的類都具有fetch()方法。 但是,提取方法為有問題的動物(狗的爪子,貓的爪子等)分配了一些獨特的功能。 例如,對於cat的fetch()將采用參數fetch(FelineCat kitty)並說:
public void fetch(FelineCat kitty) { kitty.claws = "I have claws."; }
因此,訪存方法采用了擴展抽象類Animal(因此是動物)的參數。 我已經在Animal中定義了方法fetch()以采用Animal類型的任何參數。 對我來說,這是有道理的,因為貓和狗是動物,但是Java表示GoldenRetriever無法覆蓋抽象方法fetch(Animal ani)。 為什么是這樣?
不知道我是否100%正確地理解了您的問題,但我認為我有某種解決方案。 以下代碼可以正常工作,因為您總是必須使用通用參數,但這可能不是最佳選擇,但是至少鍵入是正確的。
public abstract class Animal<T extends Animal> {
public abstract void fetch(T ani);
}
public class GoldenRetriever extends Animal<GoldenRetriever> {
@Override
public void fetch(GoldenRetriever ani) {
}
}
該方法不會覆蓋,因為參數類型不同。 您必須這樣聲明方法:
public class GoldenRetriever extends Animal {
public void fetch(Animal pup) {
即參數類型仍然必須是Animal
,即使您正在編寫擴展Animal
的類。
這是有充分的理由的。 假設您還有其他方法
public void someMethod(Animal x)
您可以傳遞任何Animal
作為參數,包括GoldenRetriever
:
GoldenRetriever gr = ...;
someMethod(gr);
假設在someMethod
您有:
public void someMethod(Animal x) {
FelineCat kitty;
...
x.fetch(FelineCat);
由於Animal
的fetch
方法可以接受任何Animal
,因此編譯器認為進行此調用必須可以,因為FelineCat
是Animal
。 它無法知道x
實際上是GoldenRetriever
。 如果它允許重寫方法采用GoldenRetriever
參數,則會出現問題,因為該參數實際上是FelineCat
,而不是GoldenRetriever
。 那么,當fetch
被多態調用,並且參數類型錯誤時,那又如何呢?
編譯器無法阻止這種情況,因為它無法知道x
的類型。 從理論上講,Java 可以允許重寫更改參數類型,並在運行時進行檢查(如果嘗試獲取GoldenRetriever
以獲取其他某種Animal
則可能拋出ClassCastException
)。 我不知道為什么他們沒有這樣做,但是我敢肯定有充分的理由不這樣做。
但是您可以進行自己的運行時檢查:
public class GoldenRetriever extends Animal {
public void fetch(Animal pup) {
if (pup instanceof GoldenRetriever) {
GoldenRetriever puppy = (GoldenRetriever)pup;
// now puppy is viewed as a GoldenRetriever, and any methods or
// instance variables particular to GoldenRetrievers can be accessed
} else {
throw new WrongSpeciesException("..."); // or whatever
}
}
}
更新:上面的答案假定方法簽名確實是您想要的。 但是按照Mixone的評論,可能是您不打算建立涉及兩個動物的操作,在這種情況下,您根本不需要參數。 像
public void fetch(GoldenRetriever pup)
假設您有一個GoldenRetriever
可以與另一個GoldenRetriever
一起GoldenRetriever
,並且您只是不希望GoldenRetriever
與其他種類的動物GoldenRetriever
做。 在那種情況下,我認為運行時檢查是最好的方法。 但是,如果您想要只對一只動物起作用的手術,那您就把它寫錯了。
覆蓋另一個方法的方法必須具有完全相同的參數,否則稱為重載。 您的fetch
方法必須這樣聲明:
public void fetch(Animal ani)
您可以將Animal
類設為通用類
abstract class Animal<TAnimal extends Animal<?>> {
public abstract void fetch(TAnimal ani);
}
class GoldenRetriever extends Animal<GoldenRetriever> {
String paws;
@Override
public void fetch(GoldenRetriever pup) {
pup.paws = "I have paws";
}
}
這稱為好奇重復模板模式
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package fetchanimal;
/**
*
* @author Amin
*/
public abstract class Animal <T>{
public abstract void fetch(T animalType);
}
現在創建一個新類
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package fetchanimal;
/**
*
* @author Amin
*/
public class FelineCat extends Animal<FelineCat> {
public String claws ;
@Override
public void fetch(FelineCat animalType) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
animalType.claws = "hello";
}
}
現在創建第三類
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package fetchanimal;
/**
*
* @author Amin
*/
public class GoldenRetriever extends Animal<GoldenRetriever>{
public String paws ;
@Override
public void fetch(GoldenRetriever animalType) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
animalType.paws = "hello" ;
}
}
只需復制粘貼代碼
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.