假设给定的类层次结构
class Region{};
class Shape extends Region{};
class Triangle extends Shape{};
class Circle extends Shape{};
有没有办法定义一个只接受Shape
或Triangle
,而不接受Circle
的方法?
我可以执行运行时类型检查并抛出异常,但编译时类型检查会好得多。
(澄清一下:通过写"给定一个类层次结构",我的意思是它不能被改变)。
你不能在编译时进行这样的检查(考虑到你当前的类层次结构),因为Circle
是一个Shape
,所以任何接受Shape
参数的方法都会接受Circle
参数。
您必须更改类层次结构或引入一些新界面。
一些选项:
-
引入一个
Shape
子类,它表示所有不是Circle
的形状(我们称之为NotCircleShape
,尽管您应该考虑对所有不是Circle
的形状的共同点进行积极的描述,并让您的方法接受该子类的参数。 -
引入一个由除
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
将成为有效参数。