首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解PHP对象类型比较

理解PHP对象类型比较
EN

Stack Overflow用户
提问于 2014-12-29 18:05:11
回答 2查看 66关注 0票数 1

继续通过Kent的测试驱动开发示例进行工作,并在PHP中重写示例。

第13章描述了如果两个对象的类型相同,则应该返回true的测试。在前面的章节中,评估是有效的,但是对于这个例子,我无法让它通过,我也不知道为什么它失败了。

给定实现表达式接口的类"Sum“:

代码语言:javascript
复制
    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);
    }
}

和表达:

代码语言:javascript
复制
    interface Expression {
    public function plus($addend);

    public function reduce($to);

}

我试图对第一个参数为Sum对象的Bank (名为reduce)调用一个方法,该对象有自己的reduce实现。但是,Java示例将第一个arg指定为接口,而不是一个具体的类:

代码语言:javascript
复制
    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);
    }
}

最后,我的理财课:

代码语言:javascript
复制
    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;
    }
}

运行此测试时:

代码语言:javascript
复制
$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类型,尽管我已经验证了每个对象的属性是否匹配:

代码语言:javascript
复制
$this->assertEquals(Money::dollar(7)->amount, $result->amount);


$this->assertEquals(Money::dollar(7)->currency, $result->currency);

这是否是由于缺乏将对象作为特定类型进行内在转换的能力造成的?我没有更改子类的实现,以前的测试仍然通过:

代码语言:javascript
复制
$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");
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-29 19:08:50

两个不同类型的对象永远不可能相等。PHP不让对象自己决定它是否等于另一个对象,就像java对所做的那样。

http://php.net/manual/en/language.oop5.object-comparison.php

在您的测试用例中,您可以自己调用eqauls方法。

代码语言:javascript
复制
$this->assertsTrue( $result->equals(Money::dollar(7)) );
票数 0
EN

Stack Overflow用户

发布于 2014-12-30 11:11:09

这与其说是一个使用phpunit的问题,不如说是一个体系结构问题。我给出了两个简单的解决方案,但是您肯定应该使用一些设计模式来改进代码。

1.

如果必须将“美元”传递给构造函数,那么定义类Dollar的意义何在?使用类Money代替。

代码语言:javascript
复制
// static factory method that returns Dollar 
// (reduces dependence on subclasses)
static function dollar($amount) {
    return new Money($amount, "USD");
}

static function franc($amount) {
    return new Money($amount, "CHF");
}

public function times($multiplier) {
    return new Money($this->amount * $multiplier, $this->currency);
}

2.

如果没有转换机制,则Dollar和返回可能具有另一种货币的Money并不是逻辑。您可以这样更改reduce of Sum方法:

代码语言:javascript
复制
public function reduce() {         
    $money = clone $this->augend;
    $money->amount = $this->augend->amount + $this->addend->amount;

    return $money;
}

-

使用这些解决方案,您的测试将如预期的那样工作:

代码语言:javascript
复制
$sum = new Sum(Money::dollar(3), Money::dollar(4));
$bank = new Bank();

$result = $bank->reduce($sum, "USD");

$this->assertEquals(Money::dollar(7), $result); // OK

因为这个断言检查对象的类和属性的相等性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27693811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档