![](/img/trans.png)
[英]Java: Creating an Instance of a Subclass from the Superclass in a static method
[英]Get instance of subclass with superclass static method
我有一個超類,我想將一個名為getInstance()
的靜態方法轉發給所有子類。
在創建子類的實例時,我然后在超類中注冊實例(可能使用哈希表,其中鍵基於getClass()
)。 然后,我希望使用前面提到的靜態方法( getInstance
),其中超類方法將返回正確類型的實例。
例如,我有一個超類A,一個子類B擴展A.我想寫一個靜態方法A.getInstance()
; 當從B( B.getInstance()
)調用時,我希望它返回我之前存儲的B的實例。
它有點難以解釋,但我將很多地使用這個超類,我寧願不將getInstance
方法編寫到每個子類中。
我該怎么做這樣的事情?
編輯:我剛剛意識到我的問題可能被誤解為創建對象的新實例。 我已經創建了實例,我希望獲得該類的現有實例
正如許多其他人在評論中指出的那樣,靜態方法無法實現您的目標。 此外,您應盡可能避免使用靜態方法,因為它們可能導致測試和維護噩夢(*)。
你將你的方法命名為“getInstance”,所以我想你想要做的是混合使用Factory和Singleton模式。 以下是一些有關這些模式的信息:
Singleton: http : //en.wikipedia.org/wiki/Singleton_pattern
工廠方法: http : //en.wikipedia.org/wiki/Factory_method_pattern
抽象工廠: http : //en.wikipedia.org/wiki/Abstract_factory
在這些日子里,兩者都不應該手工編碼(*) - 看一下像Google Guice或Spring這樣的好的“依賴注入”(DI)容器。 我不是100%確定你想要實現什么,但它看起來像一個DI容器會為你做。
編輯:這是對問題編輯的回復。 您希望接收子類的緩存實例。 在這種情況下,我仍然建議不要使用靜態方法。 您可以創建“BCache”類的單例實例(使用DI容器或手動編程),然后使用此緩存對象來查找已注冊的對象。 使用Guice作為DI容器,它看起來像這樣(警告,未經測試):
@Singleton
public class BCache {
private Map<Class<? extends B>, B> cache = ...;
public <T> T getInstance(Class<? extends T> type) {
return (T) cache.get(type);
}
}
我仍然認為可以完全使用DI容器去除緩存類。 同樣,這是使用Guice的未經測試的代碼,但它看起來像這樣:
@Singleton
public class A extends B {
public A() {
//I am not sure if you need to register in this case, because your
//DI container keeps track of the singleton instances.
super.register(this);
}
}
public class SomeClassUsingA {
@Inject private A a;
}
(*)請注意“所有概括都是錯誤的”,也就是說,在某些項目中它可能有意義,但在大多數情況下它不會。
使用靜態方法無法以良好的OOP方式完成您想要的操作。 你可以用反射或一堆if .. else if
做一些事情。
但是,您應該使用一些定義良好的設計模式,如Abstract fectory或Factory方法 。 這就是你應該去的方式,就像有人說“不要發明溫水”。
您始終可以將subClass實例分配給superClass引用。 因此,你的superClass的靜態方法可以設置或獲取一個subClass實例。 但請確保在使用之前強制轉換返回的實例。
public class A {
private static A a;
/**
* @param a the a to set
*/
public static void setA(A a) {
A.a = a;
}
/**
* @return the a
*/
public static A getA() {
return a;
}
public class B extends A {
private int index = 0;
/**
* @param index the index to set
*/
public void setIndex(int index) {
this.index = index;
}
/**
* @return the index
*/
public int getIndex() {
return index;
}
用法:
public static void main(String[] args) throws Exception {
B b = new B();
A.setA(b);
B c = (B) A.getA();
System.out.println(c.getIndex());
}
將表單getInstance()
更改為超getInstance(String class)
中的getInstance(String class)
:
public static A getInstance(String class){
if(class.equals("A")){
RegisterObject(...);//User defined method
return new A(...);
}
else if(class.equals("B")){
RegisterObject(...);//User defined method
return new B(...);
}
else if(class.equals("C")){
RegisterObject(...);//User defined method
return new C(...);
}
//... and so on
}
靜態方法無法知道使用哪個類來調用它們。 例如,如果你有A類和B類擴展A和static getInstance()
在A
實現,那么使用A
或B
調用getInstance()
沒有區別。 此外,嘗試調用B.getIntance()
將產生編譯警告(至少在Eclipse中)。
但是,您可以將該類作為getInstance()
的參數傳遞:
public class A {
public static <T extends A> T getInstance(Class<T> clazz) {
return clazz.newInstance(); // I do not catch exceptions here: do it yourself
}
}
public class B extends A {
}
...............
B b = A.getInstance(B.class);
你可以這樣做,
class A{
public static A getInstance(){
return new A();
}
@Override
public String toString() {
return "inside A";
}
}
class B extends A{
public static A getInstance(){
return new B();
}
@Override
public String toString() {
return "inside B";
}
}
內部主要:
public static void main(String[] args) {
A a1 = A.getInstance();
A a2 = B.getInstance();
System.out.println(a1.toString());
System.out.println(a2.toString());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.