2011-09-05 9 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'修飾子を仮定/適用します。 –

+0

HieghtとHightの代わりにHeightを使用することができます。 Hightはhihtenの過去分詞であり、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!だからどうすればいいの? (私は質問を編集した、plsのチェック)! – Shrey

+0

これは私が仮定するのを助ける..! thnxx :) – Shrey

+0

しかし、それはあなたが具体的な実装で高さを混乱させることができないという問題を残します。だから、あなたは身長が必要であることを知っています。高さを返すことができる必要があることを知っていますが、高さを計算するために各実装に任せることはできません(目的を破ると思います)。もちろん、 'getHeight'抽象を宣言して高さを宣言することはできませんが、毎回リターンコードを繰り返さなければならないので、変数をprivateにすることができます。 –

6

インターフェイスできません。では、インスタンス変数を定義する必要があります。メソッドのみが必要です。

Variables can be defined in interfaces、彼らが予想されるように動作しません:。彼らはfinal staticとして扱われます)

ハッピーコーディング。

7

これは、インターフェイスではなく、抽象クラスでのみ行うことができます。

abstract class代わりにinterfacepublic abstractととしてサブクラスによって実装されなければならないメソッドを宣言するとして宣言Rectangle。次にクラスTileはクラスRectangleを拡張し、Rectangleから抽象メソッドを実装する必要があります。

+0

私は最初に継承を使って考えました。 しかし、私は3つのクラスに対処しなければなりません! 1.長方形 2.タイル 3. JLabel! クラスタイルがJLabelのは、四角形を実装して拡張{} が働くだろう。! class Tile extends JLabel extends Rectangle {} woud not! – Shrey

2

Javaではできません。インターフェイスはメソッドやシグネチャと関係していますが、オブジェクトの内部状態とは関係なく実装問題です。これは意味があります。つまり、特定の属性が存在するため、実装クラスで使用する必要があるわけではありません。 getHeightは実際にwidth変数を指すことができます(実装者がサディストであると仮定します)。

(注意点として - これは、すべての言語の真実ではない、ActionScriptは疑似属性の宣言を可能にし、私はC#があまりにもないと考えている)インタフェースで

+1

C#* getters/setters *(実際には特別なメソッド呼び出し)はインタフェースに含まれている可能性があります。インスタンス変数自体はできません。 –

+0

それは私が思ったことです(それが私が疑似を言った理由です)。ActionScriptは同じことをします。 – cwallenpoole

+0

kk !!実装ではなく継承が役立ちます。しかし、これは私に新しい問題を引き起こすでしょう..!あなたは私にそれについて行く方法を提案できますか? (編集した質問を参照)thnx !! – Shrey

0

フィールドは暗黙のうちにpublic static finalです。インターフェイスの代わりに抽象クラスを使用する場合でも、すべての非定数(プリミティブオブジェクトまたは不変オブジェクト参照のpublic static final)をprivateにすることを強くお勧めします。より一般的には、 "継承への構成を好む" - TileRectangleです(もちろん、 "is-a"と "has-a"で単語ゲームをすることもできます)。

+0

タイルの形状は、長方形です。 (is-aとhave-aは私を最も混乱させます) – Shrey

+0

私はAがBを拡張する必要があると思います。実効Javaから読み込みます。 – Shrey

+1

AがBを拡張すると、BはAになりますか?あなたはそれを前に持っています。 – RichieHH

0

何かがトムによって言われています:

あなたが持っている概念を使用する場合は、問題を避ける。

実際

、代わりにを拡張し、あなたは二つの属性、タイプの長方形の1、あなたのTileクラスのタイプJLabelのいずれかを定義する実装を使用しての、そしてあなたがインターフェイスまたはいずれかにRectangleを定義することができる場合クラス。

さらに、私は通常、has-aとの関連でインターフェイスの使用を推奨しますが、あなたの状況では過剰なことになると思います。しかし、この点を決めることができるのはあなただけです(柔軟性/オーバーエンジニアリングのトレードオフ)。

4

Java 8は、メソッドの本体に使用できるインターフェイス用にdefault methodsを導入しました。 OOPによれば、インタフェースは2つのシステム/当事者間の契約として機能するべきである。

しかし、私はまだインターフェイスにプロパティを格納する方法を見つけました。私はちょっと醜い実装だと認めます。

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); 
} 
} 

このインターフェイスは醜いです。単純なプロパティを格納するためには2つのハッシュマップが必要で、デフォルトでは各ハッシュマップはデフォルトで16個のエントリを作成します。さらに、実オブジェクトが参照解除されている場合、JVMはこの弱い参照をさらに削除する必要があります。

+0

非常に興味深いが、奇妙な:)。内部クラスを削除し、静的最終マップをインターフェイス自体に保存するだけでも可能です。 – iMysak

関連する問題