2016-10-17 21 views
0

2つの類似しているが基本的に異なるアルゴリズムで使用するNodeクラスを作成しています。それらの間に共通の機能をいくつか持っている私の考えは、共有メソッドとフィールドを持つ抽象ノードクラスを作成することでした。この抽象クラスから2つの具象サブクラスのWaveNodeとEchoNodeを拡張します。抽象クラスから継承するJava

抽象クラスのメソッドの中には、Nodeのインスタンスを扱うものもありますが、このクラスにはサブクラスのインスタンスを使用したいと考えています。つまり、メソッドにWaveNodeまたはEchoNodeを指定すると、別の実装が必要です。だから抽象クラスで実装するのが最善だと思っていたので、両方のサブクラスで実装を使うことができるので、2回タイプする必要はありません。しかし、私がサブクラスにいて、WaveNodeやEchoNodeを扱っているとき、メソッドが抽象Nodeインスタンスを期待するため、コンパイルエラーが発生します。スーパークラスにメソッドを実装する方法があり、スーパークラスを拡張するさまざまなクラスがその実装を使用できます。

例を以下に示します。

Set<Node> getNeighs(){ 
    Set<Node> nei = (Set<Node>) rec.keySet();  
    nei.remove(this); 
    return nei; 
} 

このコードはマップ "rec"を取り、ノードセットにキーセットを入れます。現在のノードを削除し、すべての隣接ノードを返します。したがって、WaveNodeとEchoNodeはまったく同じコードを使用します。唯一の違いは、SetがWaveNodeまたはEchoNodeであることです。スーパークラスのNodeで実装して、2回書くのを節約したかったのです。出来ますか?

編集

コードのいくつかのより多くの投稿:

public abstract class Node { 

    private final int id; 
    Map<Node, Boolean> rec = new HashMap<Node, Boolean>(); 


    public Node(int id) { 
     this.id = id; 
    } 


    int getId() { 
     return id; 
    } 

    void addNeigh(Node neigh) { 
     rec.put(neigh, false); 
    } 

    Set<Node> getNeighs() { 
     Set<Node> nei = (Set<Node>) rec.keySet();   
     nei.remove(this); 
     return nei; 
    } 

    void printNeighbours() { 
     Set<Node> nei = getNeighs(); 
     System.out.println(this +" neighbours are: " + nei); 
    } 

    Node getSilentNeigh() { 
     for(Entry<Node, Boolean> entry : rec.entrySet()) 
     { 
      if(!entry.getValue()) 
       return entry.getKey(); 
     } 
     return null; 
    } 



public final class TreeNode extends Node { 


    boolean messageSent = false; 


    public TreeNode(int id){ 
     super(id); 
    } 

    public void sendTok(TreeNode sender){ 
     rec.put(sender, true); 
    } 

今意図したとおり、私はそれが働いていることに注意してください、それはツリーノードへのノードの戻り値の型をキャストしないために私自身のせいでした。しかし、私のコードに対するコメントは、 "あまりにも多すぎる"とか、自分のコードをクリーンアップするのに似たアドバイスを歓迎します。ありがとう

+0

すべてのあなたの実際のコード(非関連部分を削除)、およびエラーメッセージ –

+0

を投稿することができますが示されてきた方法は、しかし、パラメータを取りません。それはどのように 'rec'を受け入れますか? – Zircon

+0

あなたが望むのは、抽象クラスでいくつかの型を使うことです(つまり、 'EchoNode extends AbstractXXX ')が、私は確信していません。 –

答えて

0

Set<WaveNode>またはSet<EchoNode>Set<Node>のサブクラスではなく、キャストすることはできません。スーパークラス型(Node)の引数を使用してremove(WaveNode ..)を呼び出すことはできません。 keySetSet<Node>とすればOK、生の型はSet nei = rec.keySet();

1

です。これを行うにはジェネリックを使用してください。リターンシグネチャをSet<Node>からSet<? extends Node>に変更するか、サブクラスでタイプではなくジェネリックタイプを処理させます。

0

私は問題の精神を直感的に理解し、実行可能な解決策を考案しようとしました。コードにはもっと洗練された点があります(上記のNosretep参照)が、あまりにも詳細なので、初心者が主な点を習得するのを妨げる可能性があります。したがって、このコードは単純な作業アプローチを示唆しているだけです。

import java.util.List; 
import java.util.ArrayList; 
import java.util.Iterator; 

/* this class does everything that EVERY Node does since it defines what that means; for 
* ANY behaviors that are common to subclasses, here is where they should be implemented. 
*/ 
abstract class Node { 
    private final int id; 
    private boolean tokenSent = false; 

    public Node(int id) { 
     this.id = id; 
    } 

    int getId() { 
     return id; 
    } 

    // common behavior: other things that a Node might wish to do in context of the problem 
    public void sendTok() { 
     if (!tokenSent) { 
      // send token here 
      tokenSent = true; 
     } 
    } 

    /* common behavior: this is not really the ideal way to do this, but hopefully it makes 
    * sense in the context of the problem being solved; better would be an iterator that 
    * visits each node in the list and performs the printing, etc., but this is in the 
    * spirit of the problem 
    */ 
    public void printNeighboursOf(List<Node> list) { 
     if (list.size() > 1) { 
      System.out.print(this + "[" + getId() + "] has neighbors: "); 
      Node node; 
      Iterator<Node> iterator = list.iterator(); 
      while (iterator.hasNext()) { 
       node = iterator.next(); 
       if (!node.equals(this)) 
        System.out.print(node + "[" + node.getId() + "] "); 
      } 
     } else { 
      System.out.print(this + " has no neighbors"); 
     } 
     System.out.println(); 
    } 

    /* this method has no implementation in this class (hence its being abstract); each 
    * subclass MUST implement it (or their subclasses!), allowing differing algorithms. 
    * the signature (method name and parameter list) must be identical for every subclass 
    */ 
    public abstract int doSomeNodeBehavior(); 
} 

/* this class knows and does everything a Node knows and does, and adds a bit more; it 
* can do additional things differently or other than what EchoNode does 
*/ 
class WaveNode extends Node { 
    public WaveNode(int id) { 
     super(id); 
    } 

    public void doWaveBehavior() { 
     // do something wavy here 
    } 

    public int doSomeNodeBehavior() { 
     // do the wave algorithm 
     return 0; 
    } 
} 

/* this class knows and does everything a Node knows and does, and adds a bit more 
* can do additional things differently or other than what WaveNode does 
*/ 
class EchoNode extends Node { 
    public EchoNode(int id) { 
     super(id); 
    } 

    public void doEchoBehavior() { 
     // do something echoy here 
    } 

    public int doSomeNodeBehavior() { 
     // do the echo algorithm 
     return 0; 
    } 
} 

/* it is best to reduce the amount of behavior the Node container (ArrayList in this case) 
* does beyond what is typical for an Abstract Data Type (ADT) element; make the additional 
* behavior in other classes. visit each node to perform specific behaviors and let the 
* polymorphic behavior determine exactly what to do. Note: subclass specific behavior is 
* not possible without downcasting, and that MAY be a sign of poor design 
*/ 
public class Nodes { 
    public static void main(String[] args) { 
     List<Node> list = new ArrayList<Node>(); 
     list.add(new WaveNode(1)); 
     list.add(new WaveNode(2)); 
     Node node = new EchoNode(1); 
     list.add(node); 
     list.add(new EchoNode(2)); 

     node.printNeighboursOf(list); 
    } 
} 
関連する問題