2011-03-22 66 views
35

,同時通過我的項目的第三方庫的一些消息來源瀏覽我注意到下面的代碼模式:有一個接口/類的公共靜態內部類的優點是什麼?

public interface MyInterface { 
    public static class MyClass1 implements MyInterface { ... } 
    public static class MyClass2 implements MyInterface { ... } 
    public static class MyClass3 implements MyInterface { ... } 
} 

或者這一個:

public class MyBaseClass { 
    public static class MyClass1 extends MyBaseClass { ... } 
    public static class MyClass2 extends MyBaseClass { ... } 
    public static class MyClass3 extends MyBaseClass { ... } 
} 

真實生活中的例子:

  • SwingX:org.jdesktop.swingx.decorator.HighlightPredicateSource
  • 物質:org.pushingpixels.substance.api.renderers.SubstanceDefaultTableCellRendererSource

有這樣的代碼結構的優點是什麼?

我的第一個想法是「聚合」,但同樣的事情可以使用普通的舊包來實現。那麼何時/爲什麼使用公共內部類而不是包是更好?

+0

我沒看你已經張貼了現實生活中的例子,但一個區別是內部類可能使用外部類的私有成員,如果他們是「兄弟姐妹」(單獨的頂級類) – 2011-03-22 12:05:37

+0

好問題,則不是這種情況。就我個人而言,我建議避免這種模式,因爲它將公共課程隱藏在人們通常不期望找到它們的位置,而沒有爲折衷提供任何明顯的益處。但也許有人知道這種模式的好處應該是什麼。 – aroth 2011-03-22 12:06:29

+0

@Grzegorz,接口不能有私人成員。 – 2011-03-22 12:09:51

回答

17

我認爲這是聚合的原因,也許他們也不值得創建一個頂級的課程。我有時候會這樣做,如果有些東西需要創建一個包(將它們與其他人分開),但相應的類只能在頂級類的上下文中使用。在我看來這是一個設計決定。

裝飾者模式可能是一個很好的例子,它們可以應用在頂級類,但也許是如此簡單,他們不值得它也是頂級的。您可以通過將它們用作內部類來輕鬆顯示所有權。

對於軟件包來說,這一看起來並不明顯。您直接看到依賴類/接口。

此外,可以訪問類的私有字段,這可能是有用的,並且比私有包的範圍更細。

10

我能想到的一個用途是提供現成的界面實現,公開提供給任何人,但仍然在概念上與母接口相關聯。

只有當接口很簡單(因此內部實現類很小),它們不會太多,並且大多數接口客戶端實際需要它們時,這纔有意義。否則,他們會混淆源文件,使其更難理解。

1

內部接口必須是靜態的才能被訪問。該接口不與該類的實例關聯,但與該類本身相關聯,因此可以像Foo.Bar那樣訪問它。

4

就類和它們的內部類而言,(不適用於接口)的一個區別是內部類可能使用外部類的私有成員,如果它們是「兄弟」 '(單獨的頂級課程)。

例子:

public class MyBaseClass { 

    private static String staticField = "outer"; 

    public static class MyClass1 extends MyBaseClass { 

     public MyClass1() { 
      MyBaseClass.staticField = "inner1"; 
     } 

    } 
} 

,如果你移動的MyClass了外部類的這是行不通的。

0

我認爲公共靜態內部類的原因是「基礎」類的附加工具或實用程序。

0

當我多年前向老師問過這個問題時,他回答說,這樣你就可以爲同一個對象公開一個完全不同的界面。假設你有

public class MyBaseClass { 
    public static class MyClass1 { 
     public int myClassMethod1() {...} 
     public int myClassMethod2() {...} 
    } 
    ... 
    public void myBaseMethod1() {...} 
    public void myBaseMethod2() {...} 
} 

由於MyClass1實例訪問的MyBaseClass的內部,你可以公開相同的內部行爲的MyClass1實例或爲MyBaseClass實例作爲你需要,即使這些方法定義在兩個班都完全不同。

我從來不需要使用它,但真的很有趣。

1

這樣做,這樣可以節省你一些額外的源代碼文件,並能夠爲該類一個很好的層次名稱,而不是即org.foo.bar.XY.Defaultorg.foo.bar.DefaultXY

相關問題