Реализация классов, которые должны вести себя как необязательные

Представьте себе, если две формы пересекаются. Пересечение двух форм может быть либо другой формой, либо ничто. Если в Shape нет метода intersects(Shape), то, я считаю, правильным объектно-ориентированным решением было бы следующее:

public final class ShapesIntersection implements Maybe<shape> {
 public ShapesIntersection(Shape a, Shape b) {
 this.a = a;
 this.b = b;
 }
 @Override
 public boolean isPresent() {
 // find out if shapes intersect
 }
 @Override
 public Shape get() {
 // find the common piece of two shapes
 }
}
</shape>

В JDK Optional является классом final, а не интерфейсом. Чтобы правильно решить такие проблемы, как этот, я собираюсь написать свой собственный интерфейс Maybe, который будет выглядеть следующим образом:

public inteface Maybe<t> {
 T get();
 boolean isPresent();
 default Optional<t> asOptional() {
 return isPresent() ?
 Optional.of(get()) :
 Optional.empty();
 }
}
</t></t>

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

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

2 ответа

Как сказал rolfl, это странная идея. Представьте, что вы хотите вычислить x y для двух int s. Иногда это undefined, и вы бы использовали Maybe? И затем другая реализация, например. nCr (x, y)?

Звучит неправильно, не так ли? Проблема в том, что вы связываете происхождение вещи (пересечение, власть, выбор) с самой вещью. Но пересечение двух Shape снова не более чем a Shape (или вообще ничего, что может быть хорошо представлено через Optional. Или даже лучше с null, просто позвоните мне в старую школу).

Приближение OO здесь не имеет смысла, поскольку нет нового типа объекта. 2 2 - это то же самое, что и nCr (4, 1), и оба они точно такие же, как 4.

Другое дело, что вы должны вызвать конструктор ShapesIntersection. На самом деле это статический вызов, поэтому вместо этого вы можете написать статический вспомогательный метод.

Расширение Shape некоторым IntersectableShape может иметь смысл. Бывают случаи, когда некоторые операции достаточно распространены для такой вещи, см., Например, FluentIterable, но я сомневаюсь, что вы сделаете так много пересечений.


Вы изобретаете колесо здесь. Причина Необязательный является окончательной, потому что нет причин для ее изменения, а внутренняя семантика требует согласованности в использовании.

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

public static Optional<shape> intersection(Shape a, Shape b) {
 // compute if there is an overlap
 if (!checkOverlaps(a,b)) {
 return Optional.empty();
 }
 Shape intersection = ....
 return Optional.of(intersection);
}
</shape>

Обратите внимание, что Optional.empty() и Optional.of(....) - это методы factory, которые создают соответствующие экземпляры Дополнительного. В потоках, функциях и других поддерживающих структурах Java 8 используется ряд статических factory методов для создания экземпляров этих остальных конечных классов.

licensed under cc by-sa 3.0 with attribution.