2015-05-04 31 views
2

比方說,我有一個情況如下:只能使用獲得的靜態類型在運行時

XS類型的字段s

S由兩個類AB都實施一些相同的方法/我們都知道然後應在S實現,但不幸的是,這種情況並非如此領域擴展。

現在我想要做這樣的事情:

"A or B" downcast_field; 
if(s instanceof A) 
    downcast_field = (A)s; 
else if (s instanceof B) 
    downcast_field = (B)s; 

//do something common for the two cases but that need methods implemented both in A and B 

的問題,然後提前對具有靜態類型(出IFs的),讓我把這種方法。

我想,由於糟糕的設計,這實際上是不可能的,我必須寫兩次相同的代碼,這是醜陋的,但也許有一種解決方案,我現在沒有看到。

+0

你可以添加一個接口到'A'和'B'嗎? –

+0

設計是非常糟糕的男人!你需要改變它 – Pratik

+0

@pratik如果可能的話,我已經做到了!不幸的是,它現在必須保持這樣的狀態 – Demplo

回答

4

如果您可以更改AB,那麼您可以向兩者添加相同的接口。這將允許您將此類型設置爲downcast_field並調用方法。

如果你不能改變AB,那麼你有兩種選擇:

  • 你可以寫A2B2。將代碼從AB複製到新的類型中。這允許您修改代碼(除非您無法控制這些類型的創建)。或者,您現在也可以創建S2,它擴展了S並將通用代碼放在那裏,然後從中擴展A2/B2

  • 創建一個接口,然後創建兩個將調用委託給實際類型的實現。

    在這個解決方案中,您可以

    Wrapper downcast_field; 
    if(s instanceof A) 
        downcast_field = new AWrapper((A)s); 
    else if (s instanceof B) 
        downcast_field = new BWrapper((B)s); 
    
    downcast_field.foo(); 
    

    可以使兩個包裝延長相同類型的並且有移動通用代碼。

+0

我喜歡委託包裝類的使用,除了它爲了這個目的添加了另外三個具有'A'和'B'特定知識的類,這是一種馬虎。鑑於這種情況,我認爲這幾乎是最好的可用解決方案(除了Java 8中的東西,但有可能你沒有使用該解決方案) –

+0

是的,你可以使用方法引用,關閉或反射。引用應該很快,關閉應該沒問題,反射會很慢。 –

+0

用midClass擴展S是我最初的想法。總的來說,我認爲在任何情況下都不可能有任何優雅的解決方案。感謝少數的可能性。 @ShotgunNinja的機會是正確的,沒有java8: - / – Demplo

3

據我瞭解,您的情況如下?

public class S { 
} 

public class A extends S { 

    public void doSomething() { 
     System.out.println("A is doing something ..."); 
    } 
} 

public class B extends S { 

    public void doSomething() { 
     System.out.println("B is doing something ..."); 
    } 
} 

其實我覺得這樣的設計比較差。如果你有機會 清理這個,你應該這樣做。如果這不是一個選項以下 的解決方法是可能的...引入一個接口聲明的公共API 並使用此接口包住情況下...

public interface WrapperInterface { 
    void doSomething(); 
} 

,那麼你可以使用這個像這樣

public class Main { 

    public static void main(String[] args) { 
     WrapperInterface a=wrap(new A()); 
     WrapperInterface b=wrap(new B()); 

     a.doSomething(); 
     b.doSomething(); 
    } 

    private static WrapperInterface wrap(final S s) { 
     WrapperInterface downcast_field=null; 
     if (s instanceof A) 
      downcast_field = new WrapperInterface() { 
       @Override 
       public void doSomething() { 
        ((A) s).doSomething(); 
       } 
      }; 
     else if (s instanceof B) { 
      downcast_field = new WrapperInterface() { 
       @Override 
       public void doSomething() { 
        ((B) s).doSomething(); 
       } 
      }; 
     } 
     return downcast_field; 
    } 
} 
相關問題