复杂类型边界



假设给定的类层次结构

class Region{};
class Shape extends Region{};
class Triangle   extends Shape{};
class Circle     extends Shape{};

有没有办法定义一个只接受ShapeTriangle,而不接受Circle的方法?

我可以执行运行时类型检查并抛出异常,但编译时类型检查会好得多。
(澄清一下:通过写"给定一个类层次结构",我的意思是它不能被改变)。

你不能在编译时进行这样的检查(考虑到你当前的类层次结构),因为Circle是一个Shape,所以任何接受Shape参数的方法都会接受Circle参数。

您必须更改类层次结构或引入一些新界面。

一些选项:

  1. 引入一个Shape子类,它表示所有不是Circle的形状(我们称之为NotCircleShape,尽管您应该考虑对所有不是Circle的形状的共同点进行积极的描述,并让您的方法接受该子类的参数。

  2. 引入一个由除Circle之外的所有Shape实现的接口,并让您的方法接受该接口的参数。

分层设计的改变可以帮助你实现这一目标,如果你当然愿意重新设计class系统的话。

解决方案 1:自定义interface

具有Triangle和除Shape之外的所有其他子类Circle实现自定义interface。鉴于您的用例,我们称之为

public interface NonEllipticalShape {}

然后将方法签名更改为

public <T extends Shape & NonEllipticalShape > void method(T t) {
...
}

确实可以防止将类型Shape作为参数传递,但它看起来Shape无论如何都不应该是可实例化的类型。

因此,你会有,类似

class Circle extends Shape {}
class Triangle extends Shape implements NonEllipticalShape {}
class Rectangle extends Shape implements NonEllipticalShape {}

解决方案2:特定的工厂方法

按照此技巧操作,仅向特定子类型提供实用程序类的实例。

class MethodClass<T extends Region> {
private MethodClass() {} // private constructor
public static <T extends Triangle> MethodClass<T> instance(T c) {
return new MethodClass<T>();
}
public static <T extends Rectangle> MethodClass<T> instance(T c) {
return new MethodClass<T>();
}
public void method(T t) {
}
}

只有通过工厂方法允许的类才允许进入MethodClass实例。因此,它的方法将仅保留给特定类型T但这需要每个形状的工厂方法。

在这里,也不应接受类型T extends Shape,否则Circle将成为有效参数。

最新更新