我正在阅读书籍 Java编程语言。在解释覆盖方法的章节中,它说:
将覆盖方法(在子类中)的可访问性降低到超类中的水平会违反超类的契约...
整个文本是可以理解的。我的唯一问题是什么是超类的契约?对于Java类,契约意味着什么?
我正在阅读书籍 Java编程语言。在解释覆盖方法的章节中,它说:
将覆盖方法(在子类中)的可访问性降低到超类中的水平会违反超类的契约...
整个文本是可以理解的。我的唯一问题是什么是超类的契约?对于Java类,契约意味着什么?
在Java类中,合同类似于现实世界中的合同 - 以非技术术语来说:
这是一份协议,规定了该类将公开某些方法、某些属性和某些行为。
更多技术方面的内容,请参见此处(我添加了粗体):
如果您使用的所有Java类(包括您自己的类)都能履行其承诺,那不是很好吗?实际上,如果您确切地知道给定类做出了哪些承诺,这不是很好吗? 如果您同意,请继续阅读[...]
按合同设计
按合同设计(DBC)软件开发技术通过确保系统的每个组件达到其预期,从而确保高质量的软件。作为使用DBC的开发人员,您可以在组件的接口中指定组件合同。合同规定了该组件对客户端的期望以及客户端对其的期望。
类型(类、接口、枚举)的合同是该类型承诺遵守的,嗯,合同。它说明:
MathAverage
类的类型方法addData(float)
可能声明,每当您调用add(float)
时返回,您应该期望调用MathAverage.getAverage()
返回当前输入的正确平均值。合同在类型的javadoc中以自由形式指定。有一些工具/实践来强制执行合同,但它们是有限的,正是因为合同可以是任意的,或者在程序员错误的情况下甚至是自相矛盾的。
由于子类型(子类)可以以任意方式扩展/修改超类型方法的行为,因此它也可能违反超类型合同的某些部分。例如,扩展接受null
值和键的HashMap
,并使用某些禁止在调用其方法时使用null
值的实现。
关于类型合同的另一个重要方面是,子类型可以具有更强的合同(涵盖类型合同的子集),但不能具有更弱的合同(涵盖类型合同的超集)。
例如,如果您的类型方法'doX(n)'承诺需要O(n)
(线性)时间,则子类型中的'doX(n)'可以需要O(1)
(常数)时间,但不能需要O(n^2)
时间。
一个类的“Contract”是其公共接口,或者至少是它向其他类呈现的接口。
这意味着它包括其他类可以使用的任何元素(方法、字段、构造函数等)。
简单来说,如果您使覆盖代码不够可访问,则意味着您将违反超类的条件。
这个表达式源于“现实世界”中的合同概念。
基本上,如果您违反了与类的合同,则不需要按照您预期的方式行事。从另一个方向来看,这是类的承诺,如果您遵循它设置的规则,它将按照其API所述的方式运作。
Java中合同的一个常见例子是在覆盖equals()
时覆盖hashCode()
。根据合同,被认为相等的两个对象必须具有相同的哈希码。虽然可能编写语法正确但不遵守此规则的代码,但它可能无法正常工作,这是违反合同的程序员的错误。