Реализация концептуального наследования - PullRequest
3 голосов
/ 02 июня 2010

Я пишу пространственную структуру данных и сомневаюсь в том, что является лучшей реализацией NODE. В соответствии с моим дизайном у меня есть абстрактная сущность узла и три класса, которые наследуются от него: EMPTYNODE, FULLNODE, INTERNALNODE.

Первый не имеет конкретных данных.

Второй имеет 1 ссылку на общий элемент.

Третий имеет 2 ссылки на другие узлы.

Я нашел несколько способов реализовать эту ситуацию (которую я уже кодировал), но я не могу решить, что лучше.

Первое решение, которое я нашел, - это использование единственного класса Node, который потенциально выполняет все операции следующим образом:

private static class Node {
    private Elem elem = null;
    private Node left = null, right = null;
    public Elem getElem() {
        assert isFull();
        return elem;
    }

    public boolean isEmpty() {
        return elem == null && left == null;
    }

    public boolean isFull() {
        return  elem != null;
    }


    public boolean isInternal() {
        return elem == null && left != null;
    }
}

Второе решение - написать явное деление по классам, где каждый класс предлагает только свои методы. Очевидно, что таким образом мы обязаны выполнить несколько приведений к объектам узла.

private static abstract class Node {

    public abstract boolean isEmpty();

    public abstract boolean isFull();

    public abstract boolean isInternal();

}


private static class FullNode extends Node{

    private ITriangle elem;

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public final boolean isFull() {
        return true;
    }

    @Override
    public final boolean isInternal() {
        return false;
    }

    public Elem getElem() {
        return elem;
    }
}

Третье решение заключается в использовании наследования, позволяющего каждому классу предлагать все методы, но тип объекта должен проверяться методом "isEmpty ()" и аналогичными методами. В случае неправильного вызова мы сгенерируем исключение.

private static abstract class Node {

    public abstract boolean isEmpty();

    public abstract boolean isFull();

    public abstract boolean isInternal();

    public abstract Elem getElem();

}


private static class Empty extends Node{

    @Override
    public boolean isEmpty() {
        return true;
    }

    @Override
    public final boolean isFull() {
        return false;
    }

    @Override
    public final boolean isInternal() {
        return false;
    }

    @Override
    public Elem getElem() {
        throw new AssertionError();
    }
}

Что вы думаете об этих трех решениях?

Какой из них вы бы использовали?

Любые идеи будут оценены.

1 Ответ

1 голос
/ 02 июня 2010

Ответ будет зависеть от того, как используются узлы. После того, как узел будет создан, ему когда-нибудь нужно будет перейти с пустого на внутренний на полный или он неизменный?

Из приведенных опций, если узел является неизменным, я бы выбрал вариант 3, если вы ожидаете изменения внутреннего состояния, тогда я бы выбрал вариант 1.

Если бы вы хотели, чтобы изменчивый узел изменил поведение, я бы посмотрел на использование класса Node для хранения данных с перечислением для хранения состояний, затем узел делегировал бы соответствующее перечисление для своей реализации. Например:

public class Node {

   private enum NodeState {
      /* each state overrides specific methods to implement custom behaviour */
      FULL { public boolean isFull() { return true; } },
      INTERNAL { public boolean isInternal() { return true; } },
      EMPTY { public boolean isEmpty() { return true; } };

      /* the default behaviour */
      public boolean isFull() { return false; }
      public boolean isEmpty() { return false; }
      public boolean isInternal() { return false; }
   }

   private NodeState state = NodeState.EMPTY;
   private Elem      elem  = null;
   private Node      left  = null, right = null;

   public Elem getElem() {
      assert isFull();
      return elem;
   }

   /* TODO: constructors/mutators implement state changes go here */

   public boolean isEmpty() {
      return state.isEmpty();
   }

   public boolean isFull() {
      return state.isFull();
   }

   public boolean isInternal() {
      return state.isInternal();
   }
}

class Elem {
   /* implementation of this class */
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...