簡體   English   中英

使用超類靜態方法獲取子類的實例

[英]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 fectoryFactory方法 這就是你應該去的方式,就像有人說“不要發明溫水”。

您始終可以將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實現,那么使用AB調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM