[英]Why can't I call a method (public or static) from an Abstact class of type subclass when creating an instance of the subclass in another function?
[英]How can I get an instance of a subclass of abstract class from a static method of another class?
我有以下類結構:
DataStore類:
PStore
: public abstract class PStore ...
CStore1
和CStore2
CStore1.getInstance(Id)
和CStore2.getInstance(Id)
工人班:
public abstract class PWork...
CWork1
和CWork2
現在的情況:
類CWork1
實現了一個內部類,其中以下代碼訪問了Store:
protected class fListener implements ActionListener { public void actionPerformed(ActionEvent ae) { CStore1.getInstance(Id).someMethod(); # NOTE: someMethod() is implemented in CStore2 as well } }
我需要在CWork2
實現相同的fListener
類
作為一個優秀的小軟件開發人員,我不是簡單地將fListener
從CWork1
復制/粘貼到CWork2
類,然后在其代碼CStore1
CStore2
更改為CStore2
,而是決定將其遷移到父類。
我試圖做的:
在PStore
創建一個名為getStoreInstance(int Id)
的抽象方法: public abstract PStore getStoreInstance(int Id);
在CStore1
將該方法實現為public PStore getStoreInstance(int Id) { return CStore1.getInstance(Id); }
public PStore getStoreInstance(int Id) { return CStore1.getInstance(Id); }
到現在為止還挺好。 它編譯了所有3個Store類。
將fListener代碼從PWork
復制到CWork1
類
顯然,編譯器抱怨它對CStore1類及其方法getStoreInstance()
一無所知
現在,我決定簡單地調用新創建的getStoreInstance()
:
舊代碼: CStore1.getInstance(Id).someMethod();
新代碼: PStore.getStoreInstance(Id).someMethod();
編譯器投訴 :“無法從PStore類型中對靜態方法getStoreInstance(Id)進行靜態引用”。
Eclipse提出的唯一“修復”是使getStoreInstance()方法保持靜態,但是THAT也不起作用:
當我向抽象類的方法聲明添加一個static
修飾符時: public static abstract PStore getStoreInstance(int Id);
- 編譯器抱怨“PStore類型中的抽象方法getStoreInstance只能設置一個公開或受保護的可見性修飾符”
當我試圖使方法非抽象時: public static PStore getStoreInstance(int Id);
它抱怨說這個方法需要一個身體(非常合理)
當我試圖添加一個身體時,它要求我返回PStore對象......但是!!!! 我的抽象類PStore沒有構造函數,所以我無法返回PStore對象!
我正確地解決了這個問題嗎?
如果沒有,我該怎么辦呢?
如果我是,那么我如何解決原始投訴 “無法對非靜態方法進行靜態引用”,因為抽象類不允許我將該方法設為靜態?
它看起來對我來說,你有兩個同構的層次結構(如果我使用的是正確的術語)並且相應的類之間存在關系:
PStore PWork
/ \ / \
/ \ / \
CStore1 CStore2 CWork1 CWork2
^ ^ ^ ^
| | | |
|---------+--------------| |
| |
|---------------------|
但我不認為有一種內置的方式來表達Java中的這種關系。 不知何故,你將不得不做一些使這些關系明確的事情。 也就是說, CWork1
中需要有一些引用CStore1
東西, CWork2
中引用CStore2
,或者某種與它們相關聯的列表或地圖。
可能有一種解決這種結構的設計模式,但我現在想不到它。 所以,在我的腦海中,這里有幾個可能的解決方案(兩者都不使用反射):
將您在PWork
定義的抽象getStoreInstance
方法替換為PStore
。 在CWork1
,使用調用CStore1.getInstance
的方法覆蓋它,類似地在CWork2
覆蓋它。 然后,常見的fListener
actionPerformed
代碼將調用getStoreInstance(Id).someMethod()
,沒有類名,這可以在當前的PWork
實例上運行。 您仍然會有一些“重復”代碼(因為您必須在兩個CWork
類中實現getStoreInstance
),但它會保持最小化。
設置地圖。 這編譯(Java 8),但我沒有測試它:
class PWork { private static Map<Class<? extends PWork>,IntFunction<PStore>> storeMap; static { storeMap = new HashMap<>(); storeMap.put(CWork1.class, CStore1::getInstance); storeMap.put(CWork2.class, CStore2::getInstance); } protected PStore getStoreInstance(int Id) { return storeMap.get(getClass()).apply(Id); } protected class fListener implements ActionListener { public void actionPerformed(ActionEvent ae) { int Id = ???; // I'm assuming Id is computed from ae somehow?? getStoreInstance(Id).someMethod(); } } }
現在, getStoreInstance
在地圖中查找,使用當前PWork
對象的類( CWork1
或CWork2
)作為鍵,以確定要調用的getInstance
靜態方法。
是的,您可以在PStore上使用靜態方法並且沒有重復代碼。
使您的工作人員具有通用性,保留類令牌引用並調用
public class Worker<T extends PStore> {
private final Class<T> c;
public Worker(Class<T> c) {
this.c = c;
}
public void actionPerformed(ActionEvent ae) {
PStore.getInstance(c, Id).someMethod();
}
// other methods
}
現在對於PStore中的靜態方法,它不必是通用方法:worker不必知道返回的實際類型,它只是正確的類型。
public class PStore {
private static Map<Class<?>, List<PStore>> map = new HashMap<>();
protected PStore() {
List<PStore> list = map.get(getClass());
if (list == null) {
list = new ArrayList<>();
map.put(getClass(), list);
}
list.add(this);
}
public static PStore getInstance(Class<? extends PStore> c, int i) {
return map.get(c).get(i);
}
public abstract void someMethod();
}
這里的好處是N個實例的上限留給了PStore子類。 還要注意列表如何包含PStore實例,它們實際上是子類實例,但PStore和worker都不關心(只要它實際上是返回的所需子類,它將是)。
免責聲明:我在手機上輸入了這個,所以可能無法編譯 - 如果有問題請告訴我,我會嘗試修復它。
編譯器是正確的,因為在靜態上下文中引用實例方法不起作用。 在靜態世界中,您正在處理類級別並處理整個類的屬性。 如果您嘗試調用實例方法,編譯器如何知道您要執行實例方法的實例?
制作抽象方法不起作用,因為抽象方法必須在子類中實現。 但是,靜態方法不能被覆蓋 - 只能隱藏。 因此,如果在抽象方法上允許static
,並且您嘗試執行AbstractClass.staticMethod()
,那么運行時將使用哪些實現?
你的代碼有點難以理解,但這就是我的想法。 基於名稱, getStoreInstance(int Id)
應該確實是一個靜態方法,因為實例獲取另一個實例沒有多大意義; 這似乎更像是班級應該做的事情。 您可能想重新考慮如何構建代碼...從代碼名稱來看,您似乎應該使用類級別的方法來跟蹤類的實例,因此可能會執行類似的操作並實現getInstance()
和getStoreInstance()
作為靜態方法將是一個開始?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.