2011-09-05 79 views
47

我想知道有沒有什麼辦法的,我可以把它強制實施者類申報對象句柄/基元,因爲他們與方法做。 爲例如: -接口中的屬性/成員變量?

public interface Rectangle {  
    int height = 0; 
    int width = 0; 

    public int getHeight(); 
    public int getWidth(); 
    public void setHeight(int height); 
    public void setWidth(int width);     
} 


public class Tile implements Rectangle{ 
    @Override 
    public int getHeight() { 
     return 0; 
    } 

    @Override 
    public int getWidth() { 
     return 0; 
    } 

    @Override 
    public void setHeight(int height) { 
    } 

    @Override 
    public void setWidth(int width) { 
    } 

} 

在上述方法中,我們怎樣才能迫使瓷磚類聲明高度和使用該接口寬度屬性?出於某種原因,我希望僅通過界面來完成!

我最初以爲使用它與繼承。 但事情是我必須處理3班。

  1. 矩形
  2. 瓷磚
  3. 的JLabel!

 

class Tile extends JLabel implements Rectangle {} 

會的工作!

class Tile extends JLabel extends Rectangle {} 

woud不會!

+4

您的界面不正確。它不能包含屬性。也許你想使用抽象類? – pvoosten

+5

@lbp這[實際上會編譯](http://www.coderanch.com/t/178630/java-SCJA/certification/Instance-variables-interface);-)它只是...不是「預期的」行爲。編譯器假定/應用一個'final static'修飾符。 – 2011-09-05 17:57:16

+0

您可能喜歡使用Height而不是Hieght和Hight。 Hight是highten,hihten的過去分詞,用於呼叫,被稱爲。;) –

回答

52

接口的要點是指定公共API。一個接口沒有狀態。你創建的任何變量都是常量(所以要小心在接口中創建可變對象)。

基本上這裏的接口說的是實現它的類必須支持的所有方法。如果Java的創建者沒有在接口中允許常量,但現在已經太遲以至於無法擺脫它(並且在某些情況下常量在接口中是明智的),它可能會更好。

因爲你只是指定要實現什麼方法,所以不知道狀態(沒有實例變量)。如果你想要求每個類都有一個特定的變量,你需要使用一個抽象類。

最後,一般來說,你應該不使用公共變量,所以把變量放入界面的想法是一個不好的主意。

簡短的回答 - 你不能做你想做的事,因爲它在Java中是「錯誤的」。

編輯:

class Tile 
    implements Rectangle 
{ 
    private int height; 
    private int width; 

    @Override 
    public int getHeight() { 
     return height; 
    } 

    @Override 
    public int getWidth() { 
     return width; 
    } 

    @Override 
    public void setHeight(int h) { 
     height = h; 
    } 

    @Override 
    public void setWidth(int w) { 
     width = w; 
    } 
} 

另一種版本是:

abstract class AbstractRectangle 
    implements Rectangle 
{ 
    private int height; 
    private int width; 

    @Override 
    public int getHeight() { 
     return height; 
    } 

    @Override 
    public int getWidth() { 
     return width; 
    } 

    @Override 
    public void setHeight(int h) { 
     height = h; 
    } 

    @Override 
    public void setWidth(int w) { 
     width = w; 
    } 
} 

class Tile 
    extends AbstractRectangle 
{ 
} 
+0

kk!所以我該如何去做。 (我編輯了這個問題,請檢查)! – Shrey

+0

這會幫助我想.. ..! thnxx :) – Shrey

+0

但是這留下了一個問題,即你不能在具體實現中弄亂高度。所以你知道你需要一個高度,你知道你需要能夠返回高度,但是你不能把它留給每個實現來計算高度(我認爲這是違背了目的)。當然,你可以聲明'getHeight'抽象,而不是聲明高度,但是你必須每次重複返回代碼,這樣你才能保持變量是私有的。 –

7

你只能用抽象類來做,而不能用接口。

Rectangle聲明爲abstract class而不是interface並聲明子類必須實現的方法爲public abstract。然後,類Tile擴展類Rectangle,並且必須實現來自Rectangle的抽象方法。

+0

我最初以爲繼承使用它。 但事情是我必須處理3班。 1.矩形 2.瓷磚 3. JLabel。! class Tile擴展JLabel實現Rectangle {} 將工作。 但是 class Tile擴展JLabel擴展Rectangle {} woud not。! – Shrey

2

在Java中,你不能。接口與方法和簽名有關,它不需要處理對象的內部狀態 - 這是一個實現問題。這也是有意義的 - 我的意思是,僅僅因爲某些屬性存在,並不意味着他們必須被實施類使用。 getHeight實際上可以指向寬度變量(假設實現者是虐待者)。

(附註 - 這是不是所有的語言真實,動作允許僞屬性的聲明,我相信C#確實太)

+1

在C#* getters/setters *(實際上只是特殊的方法調用)可以在接口中 - 實例變量本身不能。 – 2011-09-05 18:02:02

+0

這就是我的想法(這就是爲什麼我說僞)ActionScript做同樣的事情。 – cwallenpoole

+0

kk !!繼承而不是實現會有所幫助。但是這會讓我產生一個新問題。你能建議我去解決這個問題嗎? (見編輯的問題)thnx! – Shrey

0

字段在接口隱含public static final。 (這些方法也是隱式公開的,所以你可以放棄public關鍵字。)即使你使用抽象類而不是接口,我強烈建議讓所有非常量(原始或不可變對象引用的public static finalprivate。更一般地說,「更喜歡組合繼承」 - 一個Tile不是一個Rectangle(當然,你可以用「is-a」和「has-a」來玩文字遊戲)。

+0

瓷磚的形狀是一個矩形.. ?? (是 - 一個,並且 - 最讓我困惑) – Shrey

+0

我想A應該擴展B當且僅當答案是'是每個B a A'是真的。閱讀Effective Java .. – Shrey

+1

如果A擴展B,B怎麼可以是A?你有它回到前面。 – RichieHH

0

發生了重要的由湯姆說:

如果使用具有-一個概念,你避免這個問題。

事實上,如果不是使用延伸工具您在Tile類中定義兩個屬性,類型長方形的,JLabel類型之一,那麼你可以定義一個Rectangle是一個接口或一類。此外,我通常會鼓勵使用與has-a有關的接口,但我想這會對你的情況造成一種矯枉過正。但是,您是唯一可以決定這一點的人(權衡靈活性/過度工程)。

4

Java 8引入了default methods接口,您可以使用這些接口進行方法驗證。根據OOP,接口應該充當兩個系統/各方之間的合同。

但我仍然發現了一種方法來實現在界面中存儲屬性。我承認這有點不好實現。

import java.util.Map; 
    import java.util.WeakHashMap; 

interface Rectangle 
{ 

class Storage 
{ 
    private static final Map<Rectangle, Integer> heightMap = new WeakHashMap<>(); 
    private static final Map<Rectangle, Integer> widthMap = new WeakHashMap<>(); 
} 

default public int getHeight() 
{ 
    return Storage.heightMap.get(this); 
} 

default public int getWidth() 
{ 
    return Storage.widthMap.get(this); 
} 

default public void setHeight(int height) 
{ 
    Storage.heightMap.put(this, height); 
} 

default public void setWidth(int width) 
{ 
    Storage.widthMap.put(this, width); 
} 
} 

這個界面很醜。爲了存儲簡單屬性,它需要兩個hashmaps,默認情況下每個hashmap默認創建16個條目。另外,當真實對象被解引用時,JVM還需要刪除這個弱引用。

+0

很有趣但很奇怪:)。你甚至可以消除內部類,只是在你的界面本身存儲靜態最終地圖。 – iMysak