Interface 接口和抽象方法中的前置条件和后置条件
我正在尝试实现自己的编程语言,目前正在进行词法分析和解析。我几乎完成了,希望添加对类不变量、前置条件和后置条件的本机支持Interface 接口和抽象方法中的前置条件和后置条件,interface,abstract-class,design-by-contract,Interface,Abstract Class,Design By Contract,我正在尝试实现自己的编程语言,目前正在进行词法分析和解析。我几乎完成了,希望添加对类不变量、前置条件和后置条件的本机支持 public withdraw (d64 amount) : this { require amount > 0; require this.balance - amount > this.overdraft; # method code d64 newBalance = this.balance - amount;
public withdraw (d64 amount) : this {
require amount > 0;
require this.balance - amount > this.overdraft;
# method code
d64 newBalance = this.balance - amount;
ensure this.balance == newBalance;
}
您还可以在类的顶部定义类不变性
class BankAccount {
invariant this.balance > this.overdraft;
# class body
}
以下是我的问题:
public withdraw (d64 amount) : this {
require amount > 0;
require this.balance - amount > this.overdraft;
# method code
d64 newBalance = this.balance - amount;
ensure this.balance == newBalance;
}
可以在抽象和接口方法中包括前置和后置条件,如下所示
public interface BankAccount {
public withdraw (d64 amount) : this {
require amount > 0;
require this.balance - amount > this.overdraft;
# no other statements (implementation)
d64 newBalance = this.balance - amount;
ensure this.balance == newBalance;
}
}
这实际上取决于您的接口是有状态的还是无状态的。为接口方法包含前置和/或后置条件是非常好的。事实上,我们一直在这样做。任何时候创建一个javadoc(或任何其他工具),都是在创建一个契约。否则,你怎么能测试任何东西?重要的是要认识到测试驱动的开发和契约式设计有很多共同点。定义契约对于正确的tdd是至关重要的——您首先要设计一个接口并为它创建一个非正式契约(使用人类可读的语言)。然后,编写一个测试以确保合同得到满足。如果我们遵循tdd classisits(),我们总是根据契约编写测试 现在,更具体地说。如果接口是有状态的,我们可以根据其他方法很容易地表达它的不变量。让我们以java <代码>列表<代码>界面为例: 如果您仔细阅读javadoc,您将看到有很多不变量。例如,
add
方法具有以下契约:
int sum(int a, int b)
Preconditions: a and b are integers (which is automatically guaranteed by static type checking in Java)
Postconditions: the result is an integer (again - type safety) which is equal to a + b
List
接口肯定是有状态的,所以我们可以使用查询方法对列表的状态进行推理,如get
、子列表
等。因此,您可以根据接口的方法表达所有不变量
对于无状态的接口,例如计算器
,我们也定义了一个契约,但它的不变量不包括任何状态。因此,例如,sum
方法可以具有以下契约:
int sum(int a, int b)
Preconditions: a and b are integers (which is automatically guaranteed by static type checking in Java)
Postconditions: the result is an integer (again - type safety) which is equal to a + b
我们的计算器
是一个无状态接口,因此在不变量中不包含任何状态
现在,让我们回到您的银行账户
示例:
按照您的描述方式,BankAccount
绝对是一个有状态的接口。事实上,它是我们称之为实体的一个模型示例(就领域驱动设计而言)。因此,BankAccount
有它的生命周期,它的状态,在它的生命周期中可以(也将)改变。因此,基于类的state方法来表示契约是非常好的。您所需要做的就是将您的金额
、余额
和透支
作为属性(如果您的语言支持)或方法移动到界面顶部-这并不重要。重要的是,金额
、余额
和透支
现在已成为界面的一部分,并构成界面的普遍语言。这些方法/属性是整个BankAccount
接口的组成部分,也就是说,它们可以用作接口合同的一部分
不久前,我实现了一个非常简单的Java契约原型,它是作为一组注释实现的,由面向方面的编程支持。我试图实现和你们类似的目标——将合同与语言结合起来,使之更加正式。这只是一个非常简单的原型,但我认为它很好地表达了这个想法。如果您感兴趣,我可能会很快将其上传到github(到目前为止,我大部分时间都在使用bitbucket)。为什么先决条件可以,而不是后决条件?@Lee因为如果接口中没有实现,您会使用什么来签入后决条件?在上面的示例中,您不知道是否存在this.balance
。不变量只与成员相关,因此如果接口可以具有属性,则可以声明关于它们的不变量。接口方法可以像任何其他方法一样具有后置条件。@Lee感谢您的回答