Java 复型界

Java 复型界,java,Java,假设一个给定的类是一个类层次结构 class Region{}; class Shape extends Region{}; class Triangle extends Shape{}; class Circle extends Shape{}; 是否有一种方法可以定义只接受形状或三角形,而不接受圆 我可以执行运行时类型检查并抛出异常,但编译时类型检查会更好 (为了澄清:通过编写“给定类层次结构”,我的意思是它不能被更改)。您不能在编译时进行这样的检查(给定您当前的类层次结构),

假设一个给定的类是一个类层次结构

class Region{};
class Shape extends Region{};
class Triangle   extends Shape{};
class Circle     extends Shape{};
是否有一种方法可以定义只接受
形状
三角形
,而不接受

我可以执行运行时类型检查并抛出异常,但编译时类型检查会更好

(为了澄清:通过编写“给定类层次结构”,我的意思是它不能被更改)。

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

您必须更改类层次结构或引入一些新接口

一些选择:

  • 引入一个子类
    Shape
    ,它表示所有非
    圆的形状(我们称之为
    NotCircleShape
    ,尽管您应该积极描述所有非
    圆的形状的共同点),并让您的方法接受该子类的参数

  • 引入一个由所有
    形状
    实现的接口,除了
    ,并让您的方法接受该接口的参数


  • 由于
    是一个
    形状
    ,因此任何接受
    形状
    参数的方法都将接受
    参数,因此在编译时不能进行这样的检查(给定当前的类层次结构)

    您必须更改类层次结构或引入一些新接口

    一些选择:

  • 引入一个子类
    Shape
    ,它表示所有非
    圆的形状(我们称之为
    NotCircleShape
    ,尽管您应该积极描述所有非
    圆的形状的共同点),并让您的方法接受该子类的参数

  • 引入一个由所有
    形状
    实现的接口,除了
    ,并让您的方法接受该接口的参数


  • 如果您当然愿意重新设计
    系统,则层次设计的更改可以帮助您实现这一点

    解决方案1:自定义
    界面

    使
    三角形
    形状
    的所有其他子类(除了
    圆形
    之外)实现自定义
    界面
    。考虑到您的用例,让我们称之为

    public interface NonEllipticalShape {}
    
    然后将方法签名更改为

    public <T extends Shape & NonEllipticalShape > void method(T t) {
        ...
    }
    
    解决方案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) {
    
        }
    
    }
    
    class方法类{
    私有MethodClass(){}//私有构造函数
    公共静态MethodClass实例(TC){
    返回新的MethodClass();
    }
    公共静态MethodClass实例(TC){
    返回新的MethodClass();
    }
    公共无效法(T){
    }
    }
    
    只有通过工厂方法允许的类才允许进入
    MethodClass
    实例。因此,其方法将仅保留用于特定类型
    T
    ,但这将需要每个形状的工厂方法


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

    如果您当然愿意重新设计
    系统,则分层设计中的更改可以帮助您实现这一点

    解决方案1:自定义
    界面

    使
    三角形
    形状
    的所有其他子类(除了
    圆形
    之外)实现自定义
    界面
    。考虑到您的用例,让我们称之为

    public interface NonEllipticalShape {}
    
    然后将方法签名更改为

    public <T extends Shape & NonEllipticalShape > void method(T t) {
        ...
    }
    
    解决方案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) {
    
        }
    
    }
    
    class方法类{
    私有MethodClass(){}//私有构造函数
    公共静态MethodClass实例(TC){
    返回新的MethodClass();
    }
    公共静态MethodClass实例(TC){
    返回新的MethodClass();
    }
    公共无效法(T){
    }
    }
    
    只有通过工厂方法允许的类才允许进入
    MethodClass
    实例。因此,其方法将仅保留用于特定类型
    T
    ,但这将需要每个形状的工厂方法


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

    从面向对象的角度来看,
    Circle
    形状。因此,无法声明一个接受形状的方法,然后假装圆不是形状。您可以使形状和三角形(但不是圆)实现接口,并将此接口传递给您的方法,而不是将区域类传递给您的方法。@CostisAivalis if
    shape
    实现接口,
    Circle
    也实现了它<代码>圆
    是一个
    形状
    @realpointist是的,我知道
    是一个
    形状
    。这是我问题的基础。如果不是的话,它本来会是的simple@CostisAivalis该问题假设一个给定的层次结构从面向对象的角度来看,
    是一个
    形状
    。因此,无法声明一个接受形状的方法,然后假装圆不是形状。您可以使形状和三角形(但不是圆)实现接口,并将此接口传递给您的方法,而不是将区域类传递给您的方法。@CostisAivalis if
    shape
    实现接口,
    Circle
    也实现了它<代码>圆
    是一个
    形状
    @realpointist是的,我知道
    是一个
    形状
    。这是我问题的基础。如果不是,