OOP:实现具有更宽签名的接口方法

时间:2012-11-10 16:11:43

标签: 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的超类型)

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

1 个答案:

答案 0 :(得分:2)

简答:

请考虑以下示例:

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

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?
    }
}

在层次结构中向上移动意味着超类型具有较少的子类型的功能和属性,因此接口风险不受尊重: 如果可以抽象一个param类型,那么就有可能有一个实现接口的类,将方法METHOD f (ANY_TYPE) : NIL重新定义为METHOD f {{1}因为所有类型都从Object继承。

因此可以定义一个将数字传递给(OBJECT) : NIL f METHOD的类,还可以定义另一个将字符串传递给它的类,有可能破坏接口签名和与客户签订合同(见下文)。

答案很长:

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

与客户的合同是在类中的接口NOT中指定的(该合同将为您的高级黑盒组件设计建模)。

实际上,界面指定了类方法的签名(以几乎合法的方式),并且从Design By Contract的角度来看,这是设计中最重要的部分。 类是接口的化身,需要公开它。

因此,接口定义了类的Abstract Data Type行为,如果类可以更改该定义,那么它可以与客户端更改签名的合法合同。

我们正在改变合同,如果抽象化params,因为更抽象的数据类型将具有不同的行为和更具体的行为和属性。 请参阅上面的示例,其中服务提供者(类)更改签名,从而更改合同。 合同在签订后发生变更后,没有人会感到高兴。

这不限制设计,因为接口在java中可以有多个继承。此外,从JDK5,您可以使用Generics接口。

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

(INT) : NIL

然后在子类中我们对类型没有约束。

请注意,在这种情况下,合同没有指定任何有关参数类型的内容,因此客户不应该期待任何事情,也不能起诉我们。