2017-07-19 32 views
2

私は何をしようとしているかを説明するための簡単なインターフェイス継承の例を書きました。インターフェイスを実装するクラスの変数を呼び出す/代入する

interface Fruit{ 
    public void taste();  
} 


class Banana implements Fruit { 
    public String name = "Banana"; 
    public void taste(){ 
     System.out.println("yummy banana!"); 
    } 


class Strawberry implements Fruit { 
    public String name = "Strawberry"; 
    public void taste(){ 
     System.out.println("yummy strawberry!"); 
    } 
} 

class Lunch<Fruittype implements Fruit> { 
    public Fruittype fruit; 

    public void tasteit() { 
     System.out.println("I'm going to eat a"+ fruit.name + "!"); 
     // error: name cannot be resolved or is not a field 
     fruit.taste(); 
    } 
} 

class exec { 
    public static void main(String[] args) { 
      Lunch<Banana> bananalunch = new Lunch<>; 
      bananalunch.fruit = new Banana(); 
      bananalunch.tasteit(); 
    } 
} 

だから、バナナとイチゴがフルーツを実装しています。クラスランチでは、果物の名前とその機能の味を呼ぼうとしています。 (参照:コメントのエラーを)機能味がうまく動作しますが、私は名前を呼び出すことはできません呼び出し中:私はバナナを食べに行くよ

は出力を募集! おいしいバナナ!

私が言ったように、おいしいバナナは動作しますが、その名前は解決できません。私は "public String name =" default ""を宣言しようとしました。 Fruitインタフェースでは、その後、それを呼び出すことができますが、実際のクラスの名前ではなく、常に「デフォルト」と表示されます。

インタフェースを実装する汎用タイプのメンバーを取得する方法はありますか? P.P.私はこのようにしなければなりません。もちろん、このコードは表現のためだけですが、私はこの問題に遭遇したより複雑なコードをはるかに多く持っています。そして、必要でない場合には再構成したくありません。

ありがとうございます!

+4

インタフェースに 'getName()'メソッドを追加し、そのインタフェースの実装で標準のgetter/setterメソッドを実装します。 (もちろん、「名前」はプライベートにしてください) – David

答えて

3

問題は、fruit.getName()メソッドではなく、fruit.nameのインスタンスメンバーに直接アクセスしようとしたことが原因です。

getterメソッドを使用すると、正しいメソッドが実行され、必要な出力が返されます。

つまり、この特定の例では、基本クラスに単一のメソッドを持たせ、その基本クラスに単一の_name変数を持ち、実際のタイプに基づいて異なる値に初期化しますフルーツクラス。

一方、Fruitが基本クラスではなくインターフェイスであることを確認すると、そのインターフェイスを実装する各クラスに異なる値を返すgetName()メソッドを持たせることができます。例えば

class Strawberry implements Fruit { 
    public String name = "Strawberry"; 
    public void taste(){ 
     System.out.println("yummy strawberry!"); 
    } 
} 

はなる:

class Strawberry implements Fruit { 
    public String getName() { 
     return "Strawberry"; 
    } 
    public void taste() { 
     System.out.println("yummy strawberry!"); 
    } 
} 

あなたは、インターフェイスにgetName()を追加する必要があります:

interface Fruit { 
    public String getName(); 
    public void taste();  
} 

は最後に、あなたのLunchクラスは次のようになります。

class Lunch<Fruittype implements Fruit> { 
    public Fruittype fruit; 

    public void tasteit() { 
     System.out.println("I'm going to eat a "+ fruit.getName() + "!"); 
     fruit.taste(); 
    } 
} 
+0

ありがとう!私はそれについて考えなかった – kalu

0

ケースがclass implements interfaceの場合、このクラスのオブジェクトはinterfaceに記述されているものを実行できることを意味します。

たとえば、すべての平面形状に面積があります。したがって、インタフェースを決定することができます:

interface PlaneShape { 
    int getArea(); 
} 

正方形の面積はエッジの積です。円の面積は、 の円の半径と、pi数を2で割ったものです。したがって:

class Square implements PlaneShape { 
    public int edge = 5; 

    public int getArea() { 
     return edge*edge; 
    } 
} 

class Circle implements PlaneShape { 
    public int radius = 5; 
    public int pi = 3.14; 

    public int getArea() { 
     return radius*radius*pi/2; 
    } 
} 

インターフェイスは抽象化に使用します。 AreaCalculatorは平面形状で動作するため、特定の種類の平面形状から抽象化されます。 AreaCalculatorは、getArea()メソッドを実行することによってどのシェイプでもエリア値を得ることができることを知っています。 AreaCalculatorは、edgeradiusのような特殊な形状フィールドについては何も知らない。このところで

class AreaCalculator<S implemets PlaneShape> { 
    public S shape; 

    public int calculateArea() { 
     shape.getArea(); 
    } 
} 

、あなたの例では、Lunch<Fruittype implements Fruit>クラスは内部名が、それはこのフィールドを「見ない」果物については何も知らない、それが唯一の方法taste()をinvocateすることができます。インターフェイスにメソッドgetName()を追加して実装する必要があります。

name="default"の件名はinterfaceです。それはインタフェースの文脈で宣言され、実装には関係がありません。

関連する問題