实现应该表现为Optional的类

时间:2015-04-19 15:43:33

标签: java oop optional

想象一下,找出两个形状是否相交。两个形状的交集可以是另一种形状,也可以不是。如果intersects(Shape)中没有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
    }
}

在JDK中,Optionalfinal类,而不是接口。为了正确解决像这样的问题,我将编写自己的Maybe接口,如下所示:

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

如果我在需要可选行为时坚持使用Maybe解决方案,可能会有什么警告?此外,这项任务似乎非常普遍。我是通过引入自己的Maybe界面来重新发明轮子的吗?

我应该补充说,使用单独的类和接口的整个麻烦是省略使用静态方法实现行为。

2 个答案:

答案 0 :(得分:8)

你在这里重新发明轮子。 Optional是最终的原因是因为没有理由改变它,并且内部语义要求在整个使用过程中保持一致。

这里真正的问题是构造函数的逻辑。您不应该使用构造函数来确定交集的逻辑。你想要的是一个(静态?)方法,为你执行计算,并返回相关的可选。

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

请注意,Optional.empty()Optional.of(....)是工厂方法,可以创建Optional的适当实例。 Java 8流,函数和其他支持结构使用许多静态工厂方法来创建这些最终类的实例。

答案 1 :(得分:5)

正如rolfl所说,这是一个奇怪的想法。想象一下,您想为两个int计算 x y 。有时候它是未定义的,你会实现Maybe<Integer>吗?然后是另一个例如nCr( x y )?

这声音不对,不是吗?问题在于你将事物的起源(交集,权力,选择)绑定到事物本身。但是两个Shape的交集只不过是一个Shape(或者根本没有,可以通过Optional很好地表示。或{{1}更好只是叫我老派。

OO aproach在这里毫无意义,因为没有新的对象。 2 2 与nCr(4,1)完全相同,两者都与4相同。

另一件事是你必须调用null构造函数。这实际上是一个静态调用,所以你也可以编写一个静态辅助方法。

将某些ShapesIntersection扩展Shape可能有意义。有些情况下某些操作对于这样的事情是足够普遍的,例如参见FluentIterable,但我怀疑你会做那么多的十字路口。