一个类的“contract”是什么意思?

40

我正在阅读书籍 Java编程语言。在解释覆盖方法的章节中,它说:

将覆盖方法(在子类中)的可访问性降低到超类中的水平会违反超类的契约...

整个文本是可以理解的。我的唯一问题是什么是超类的契约?对于Java类,契约意味着什么?


请查看维基百科上的契约式设计链接和c2.com上的相关资料链接 - Sadeq Dousti
8个回答

41

在Java类中,合同类似于现实世界中的合同 - 以非技术术语来说:

这是一份协议,规定了该类将公开某些方法、某些属性和某些行为。

更多技术方面的内容,请参见此处(我添加了粗体):

如果您使用的所有Java类(包括您自己的类)都能履行其承诺,那不是很好吗?实际上,如果您确切地知道给定类做出了哪些承诺,这不是很好吗? 如果您同意,请继续阅读[...]

按合同设计

按合同设计(DBC)软件开发技术通过确保系统的每个组件达到其预期,从而确保高质量的软件。作为使用DBC的开发人员,您可以在组件的接口中指定组件合同。合同规定了该组件对客户端的期望以及客户端对其的期望。


1
合同和规格有区别吗?看起来合同只是规格的人性化术语,因为人们同意合同,但机器和流程是按照规格构建的。(至少在我对英语的理解中是这样。) - Buttons840
5
“Specification” 可以理解为实现细节,即受保护和私有方法和属性。而“Contract” 仅指公共方法和属性。 - dgvid
1
我这样想:在软件项目中,当你雇用一个供应商时,会有一份工作合同(通常比较笼统),以及(希望有)一份更详细的具体要求文档。规格说明更类似于具体要求文档,因为它实现了合同,并具体说明了如何实现。 - David

8

类型(类、接口、枚举)的合同是该类型承诺遵守的,嗯,合同。它说明:

  • 构造函数和/或方法可以接受哪些可接受的参数;
  • 你应该期望这种类型做什么或不应该做什么。例如,它可能声明你应该期望这个类是线程安全的或非线程安全的;
  • 该类型支持什么不变量。例如,计算输入平均值的MathAverage类的类型方法addData(float)可能声明,每当您调用add(float)时返回,您应该期望调用MathAverage.getAverage()返回当前输入的正确平均值。
  • 一般来说,您的类型可以指定其所有子类型必须遵循的任何约束条件。例如,它可以说“此类型的任何方法执行时间不能超过1秒”。

合同在类型的javadoc中以自由形式指定。有一些工具/实践来强制执行合同,但它们是有限的,正是因为合同可以是任意的,或者在程序员错误的情况下甚至是自相矛盾的。

由于子类型(子类)可以以任意方式扩展/修改超类型方法的行为,因此它也可能违反超类型合同的某些部分。例如,扩展接受null值和键的HashMap,并使用某些禁止在调用其方法时使用null值的实现。

关于类型合同的另一个重要方面是,子类型可以具有更强的合同(涵盖类型合同的子集),但不能具有更弱的合同(涵盖类型合同的超集)。 例如,如果您的类型方法'doX(n)'承诺需要O(n)(线性)时间,则子类型中的'doX(n)'可以需要O(1)(常数)时间,但不能需要O(n^2)时间。


3
这意味着覆盖父类或接口上的方法必须按照合同定义的方式进行操作。否则,结果是未定义的。

3

一个类的“Contract”是其公共接口,或者至少是它向其他类呈现的接口。

这意味着它包括其他类可以使用的任何元素(方法、字段、构造函数等)。


1
在Java或任何其他面向对象的语言中,类或接口的契约通常指该类接口公开暴露的方法(或函数)和属性(或字段或属性),以及适用于这些公共方法和属性的任何注释或文档。
在类和子类之间的关系中,任何受保护的方法或属性都将被视为“公开暴露”,因为它们向子类公开。

0

在编写Java或任何编程语言的程序时,有许多原则需要遵循。这些原则取决于您使用的编程语言。您可以通过设计契约维基百科页面了解更多关于契约的内容。


0

简单来说,如果您使覆盖代码不够可访问,则意味着您将违反超类的条件。


0

这个表达式源于“现实世界”中的合同概念。

基本上,如果您违反了与类的合同,则不需要按照您预期的方式行事。从另一个方向来看,这是类的承诺,如果您遵循它设置的规则,它将按照其API所述的方式运作。

Java中合同的一个常见例子是在覆盖equals()时覆盖hashCode()。根据合同,被认为相等的两个对象必须具有相同的哈希码。虽然可能编写语法正确但不遵守此规则的代码,但它可能无法正常工作,这是违反合同的程序员的错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接