OOP:实现具有更广泛签名的接口(interface)方法

标签 oop inheritance interface covariance design-by-contract

假设我有一个界面:

INTERFACE `IFace` (
  METHOD `f` (INT) : NIL
)

我想用具有更广泛签名的方法来实现它:

CLASS `A` IMPLEMENTS `IFace` (
  METHOD `f` (NUMBER n) : NIL (
    PRINT n
  )
)

(假设 NUMBER 是 INT 的父类(super class)型)

为什么这是不可能的?或者哪些编程语言支持这个?

最佳答案

简短回答:

考虑以下示例:

第一个示例(来自您的示例):

INTERFACE `IFace` (
  METHOD `printFibonacci` (INT) : NIL
)

CLASS `A` IMPLEMENTS `IFace` (
  METHOD `printFibonacci` (NUMBER n) : NIL (
    //what if the number is a not an integer? Can we guarantee to the client that we are respecting the method signature?
  )
)

第二个示例:

public interface Talking {

    public void speak(Human human);

}


public class Employee implements Talking {

    public void speak(Animal animal) {
        // can we speak with a cockroach?
    }
}

在层次结构中向上意味着父类(super class)型具有较少的子类型功能和属性,因此接口(interface)有不被尊重的风险: 如果可以抽象参数类型,那么就可以有一个实现接口(interface)的类,重新定义方法 METHODf(ANY_TYPE) : NILMETHODf(OBJECT) : NIL 因为所有类型都继承自 Object。

因此,可以定义一个将数字传递给 METHODf(INT) : NIL 的类,也可以定义另一个将字符串传递给它,冒着破坏接口(interface)签名和与客户端的契约(Contract)的风险(见下文)。

长答案:

实现接口(interface)的主要目的是将其公开给客户端,客户端只知道该接口(interface),而不知道实现它的类。 通过这种方式,您可以向客户端传递实现相同接口(interface)的不同类,从而在不改变客户端的情况下改变软件的功能。

与客户端的契约(Contract)在接口(interface)中指定,而不是在类中指定(该契约(Contract)将对您的高级黑盒组件设计进行建模)。

事实上,接口(interface)指定了类方法的签名(以几乎合法的方式),并且来自 Design By Contract观点是设计中最重要的部分。 类是需要公开它的接口(interface)的化身

因此该接口(interface)定义了 Abstract Data Type类的行为,如果类可以更改该定义,那么它可以破坏与客户端更改签名的“合法”契约(Contract)。

如果抽象参数,我们也会改变契约,因为更抽象的数据类型将具有与更具体的数据类型不同的行为和属性。 请参阅上面的示例,其中服务提供者(类)更改签名并因此更改契约(Contract)。 如果契约(Contract)签订后又发生变化,没有人会高兴。

这并不限制设计,因为接口(interface)在java中可以有多重继承。此外,从 JDK5 开始,您可以使用 Generics有接口(interface)。

因此我们可以使用泛型执行以下操作:

public interface IFace<T> {
    public void f(T n); 
}

然后在子类中我们对类型没有限制。

请注意,在这种情况下,契约(Contract)没有指定有关参数类型的任何内容,因此客户不应期望任何内容,也不能起诉我们。

关于OOP:实现具有更广泛签名的接口(interface)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13323644/

相关文章:

java - 对象类型列表和扩展类型的对象列表之间的区别

python - 动态更改遗产树中的给定类并将其替换为另一个并初始化它

java - 设计: extend JPanel twice or pass JPanel as parameter?

java - 就像父类(super class)成员一样,父类(super class)构造函数是否构成子类对象状态的一部分?

javascript - Sencha 触摸2 : How to get (multiple) instances of a base class

c++ - C++11 中的可变参数模板和多重继承

java - 为接口(interface)方法指定抽象或不指定有什么区别?

php - __autoload 检测并包含接口(interface)

PHP OOP核心框架

c++ - 了解 OOP 的良好习惯和 C++ 中的多重继承