【问题标题】:Java inheriting from abstract classJava继承自抽象类
【发布时间】:2016-10-17 17:12:19
【问题描述】:

我正在创建一个 Node 类,用于两种相似但根本不同的算法。在它们之间有一些共同的功能,我的想法是创建一个具有共享方法和字段的抽象节点类。从这个抽象类扩展两个具体的子类 WaveNode 和 EchoNode。

抽象类中的一些方法处理节点的实例,但我想将这个公共代码与子类的实例一起使用,也就是说,如果你给方法一个 WaveNode 或一个 EchoNode,那么这个方法就不需要了不同的实现。所以我认为最好在抽象类中实现它,并且两个子类都可以使用该实现,所以我不必输入两次。但是,当我在我的子类中并且我正在处理 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 来实现它,以节省我写两次的时间。有可能吗?

编辑

发布更多代码:

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

请注意,我现在让它按预期工作,没有将 Node 的返回类型转换为 TreeNode 是我自己的错。但是,欢迎对我的代码“做太多”的任何 cmets 或关于清理我的代码的类似建议。谢谢

【问题讨论】:

  • 您能否发布所有实际代码(删除不相关的部分)以及错误消息
  • 不过,您展示的方法不带参数。它如何接受rec
  • 我认为你想要的是在抽象类上使用某种类型(即EchoNode extends AbstractXXX&lt;EchoNode&gt;),但我不确定
  • 对不起,我只需要将返回 Node 的方法的返回类型转换为 TreeNode。我认为这很危险,因为您应该尽量避免放弃,但它似乎有效并且没有给我错误。我目前正在学习继承,所以可能是一个菜鸟错误。谢谢

标签: java inheritance polymorphism abstract-class


【解决方案1】:

使用泛型来执行此操作,而不是在 Node.js 上专门键入。将返回签名从 Set&lt;Node&gt; 更改为 Set&lt;? extends Node&gt; 或让子​​类处理泛型类型而不是其类型。

【讨论】:

    【解决方案2】:

    Set&lt;WaveNode&gt;Set&lt;EchoNode&gt; 不是 Set&lt;Node&gt; 的子类,不能转换为它;并且您不能使用超类类型 (Node) 的参数调用 remove(WaveNode ..)。如果您将 keySet 设置为 Set&lt;Node&gt; 就可以了,或者使用原始类型:Set nei = rec.keySet();

    【讨论】:

      【解决方案3】:

      为了提供更多帮助,我试图凭直觉了解问题的本质并提出可行的解决方案。代码可以完成许多更复杂的点(参见上面的 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);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-07
        • 2013-08-04
        • 2011-03-15
        • 2016-07-02
        • 2021-10-24
        相关资源
        最近更新 更多