Способы достижения эффективных черт Java?

Пожалуйста, дайте мне знать, если это не подходит, как сформулировано (в частности, будет ли Programmers.SE или что-то лучше для вопроса.)

Хорошо. Поэтому у меня есть ряд "черт", которые я сейчас выражаю как интерфейсы. Назовите их "обновляемыми" и "разрушаемыми". Выражение им как интерфейсов имеет недостаток, что я не могу делиться поведением между всеми "разрушаемыми" компонентами; с другой стороны, выражая их как абстрактные классы, я не могу смешивать и сопоставлять, явно не определяя смешанную черту как еще один абстрактный класс ( "UpdateableAndDestructible" ), и, кроме того, это похоже на злоупотребление функциональностью абстрактного класса в этой точке. Это, вероятно, то, что я в конечном итоге сделаю, если нет более чистых способов решения этой проблемы.

Каковы мои возможности в отношении чистых решений Java для этой головоломки? Возможно ли, чтобы я описывал общее поведение, а затем смешивал и сопоставлял, как мне кажется, без явного описания каждой перестановки, которую я буду использовать?

Ответ 1

Возможно, вы могли бы достичь цели, используя сочетание интерфейсов и реализаций по умолчанию.

Как

public interface Updatable {
  void updated();
}

public interface Loadable {
  void load();
}

public class DefaultUpdatable implements Updatable {
 ...
}

public class DefaultLoadable implements Loadable {
 ...
}

public class SomeObject implements Updatable, Loadable {
  private final Updatable updatable = new DefaultUpdatable();
  private final Loadable loadable = new DefaultLoadable();

  public void load() {
    this.loadable.load();
  }

  public void updated() {
    this.updatable.updated();
  }
}

Все еще шумно и, возможно, не так гибко, как вам хотелось бы, но, может быть, немного чище, чем делать вещи UpdatableAndDestructable.

Ответ 2

Я не думаю, что есть довольно приемлемое решение этой проблемы, но, возможно, несколько работоспособных в зависимости от того, насколько вы презираете шаблон.

Вы можете определить признак как другой интерфейс класса +, который принимает объект экземпляра в качестве первого параметра. И они реализуют интерфейс с классом, который вы хотите получить. Затем создайте методы-заглушки, которые вызывают методы на основе признаков.

public class MyClass implements MyTrait {
    @Override
    public void doSomething() {
        MyTraitImpl.doSomething(this);
    }
}

И затем для самого признака:

public interface MyTrait {
    public void doSomething();
}

public class MyTraitImpl {
    public static void doSomething(MyTrait obj) {
        // do something with obj
    }
}

Как говорит Эрнест Фридман-Хилл, Scala делает это для вас (как я понимаю, так оно реализует черты JVM).

Ответ 3

Я знаю, что вы сказали "чистая Java", но это что-то Scala. Ограничения на языке Java являются сильным драйвером для людей, чтобы использовать другие языки JVM...

Ответ 4

Если вы рассматриваете использование lombok как чистой Java, вы можете упростить свою жизнь, используя @Delegate следующим образом:

public class SomeObject implements Updatable, Loadable {
    @Delegate private final Updatable updatable = new DefaultUpdatable();
    @Delegate private final Loadable loadable = new DefaultLoadable();
}