复杂类型边界

时间:2018-03-06 10:32:42

标签: java

假设给定一个类层次结构

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

有没有办法定义仅接受ShapeTriangle但不接受Circle的方法?

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

2 个答案:

答案 0 :(得分:3)

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

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

一些选项:

  1. 引入一个Shape的子类,代表所有不是Circle的形状(让我们称之为NotCircleShape,但你应该想到一个积极的描述所有不是Circle的形状的共同点是什么,让你的方法接受该子类的参数。

  2. 介绍除Shape之外的所有Circle实现的接口,并让您的方法接受该接口的参数。

答案 1 :(得分:1)

如果您当然愿意重新设计 class系统,那么层次结构设计的变化可以帮助您实现这一目标。

解决方案1 ​​:自定义interface

Triangle以及ShapeCircle以外的所有其他子类实现自定义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 :具体工厂方法

关注this trick并仅将实用程序类的实例提供给特定的子类型。

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将成为有效参数。