Способы достижения эффективных черт 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();
}