【发布时间】:2014-12-30 19:18:30
【问题描述】:
继续完成 Kent Beck 的测试驱动开发示例并用 PHP 重写示例。
第 13 章描述了一个测试,如果 2 个对象属于同一类型,则该测试应返回 true。在前几章中,评估是有效的,但是对于这个示例,我无法通过它,而且我不确定它为什么会失败。
给定一个实现 Expression 接口的类“Sum”:
class Sum implements Expression {
public $augend;
public $addend;
public function __construct($augend, $addend)
{
$this->augend = $augend;
$this->addend = $addend;
}
// impl of Expression interface, but this smells to me, dupe implementation
// also in Money
public function plus($addend) {
return new Sum($this, $addend);
}
public function reduce($to) {
$amount = $this->augend->amount + $this->addend->amount;
return new Money($amount, $to);
}
}
和表达式:
interface Expression {
public function plus($addend);
public function reduce($to);
}
我正在尝试调用 Bank 对象(称为 reduce)的方法,该对象的第一个参数是 Sum 对象,它有自己的 reduce 实现。但是,Java 示例将第一个 arg 指定为接口,而不是具体类:
class Bank {
// the book defines the $source param as type Expression, which is legal
// in Java but not in PHP
public function reduce($source, $to) {
return $source->reduce($to);
}
}
最后,我的 Money 课程:
class Money implements Expression {
public $amount;
public $currency;
public function __construct($amount, $currency) {
$this->amount = $amount;
$this->currency = $currency;
}
public function currency(){
return $this->currency;
}
public function equals($compareObject) {
return $this->amount == $compareObject->amount
&& $this->currency() == $compareObject->currency();
}
// static factory method that returns Dollar
// (reduces dependence on subclasses)
static function dollar($amount) {
return new Dollar($amount, "USD");
}
static function franc($amount) {
return new Franc($amount, "CHF");
}
public function times($multiplier) {
return new Money($this->amount * $multiplier, $this->currency);
}
// impl of Expression interface
public function plus($addend) {
return new Sum($this, $addend);
}
public function reduce($to) {
return $this;
}
}
运行此测试时:
$sum = new Sum(Money::dollar(3), Money::dollar(4));
$bank = new Bank();
$result = $bank->reduce($sum, "USD");
$this->assertEquals(Money::dollar(7), $result); //FAIL
断言失败,表明 $result 是 Money 类型而不是 Dollar 类型,即使我已经验证每个对象的属性都匹配:
$this->assertEquals(Money::dollar(7)->amount, $result->amount);
$this->assertEquals(Money::dollar(7)->currency, $result->currency);
这是缺乏将对象本质上转换为特定类型的能力的结果吗?我没有更改子类的实现,之前的测试仍然通过:
$five = Money::dollar(5);
$this->assertEquals(new Money(10, "USD"), $five->times(2));
$this->assertEquals(new Money(15, "USD"), $five->times(3));
$this->assertEquals(get_class($five), "Dollar");
【问题讨论】: