【问题标题】:How do I avoid inheritance and still make it look as though I'm calling one class?如何避免继承并仍然让它看起来好像我正在调用一个类?
【发布时间】:2015-03-12 18:08:22
【问题描述】:

我对如何在不使用继承的情况下正确完成以下操作很感兴趣:

我想像这样在我的应用中拨打电话:

// I don't want to do this:
// $temp = new Sedan;
// $myCar = new Car($temp);
// $myCar->paint();

// nor this:
// $myCar = new Car(new Sedan);
// $myCar->paint();

// Instead I want this:
$myCar = new Sedan;   
$myCar->paint();

paint 方法实际上是 Car 类的一部分:

class Car {
    private $carToPaintOn;  // <-- Instance of Sedan would be stored here      

    public function __construct(CarInterface $car){
        $this->carToPaintOn = $car;
    }

    public function paint(){
        // paint some car
    }
}

如果不使用继承,类Sedan(或CoupeConvertable 等...)会是什么样子? 类代码必须使用行业标准设计模式并遵循干净和可测试代码的准则。另外请避免重复 paint 方法,将其添加到 Sedan。

编辑:事后看来,我应该将“汽车”类命名为别的东西,并给它一个名为“Paintable”的接口,以便更好地理解这一点。

【问题讨论】:

  • 你的教授不希望我们回答你的作业。
  • 看看我的个人资料,我不在大学。 :-p
  • 但我只是想解决我与其他人(如果你必须知道的话)的讨论,哈哈!
  • 不可能。您不能实例化 Sedan 对象并让它返回 Car 对象。为了接近,您可以结合工厂模式和委托模式。但即使这样也不能满足您的所有要求,例如间接实例化和自动依赖注入。
  • 孩子们,请不要在家里这样做。

标签: php inheritance design-patterns composition php-5.5


【解决方案1】:

这应该是继承,因为Sedan IS A car,但Sedan没有HAVE A车,但如果你真的想避免它...

class Sedan implements CarInterface {
    private $car;
    public function __construct() {
        $this->car = new Car($this);
    }
    function __call($method_name, $args) {
        if (!method_exists($this, $method_name)) {
            return call_user_func_array(array($this->car, $method_name), $args);
        }
    }
}

【讨论】:

  • 我知道,我只是认为汽车很容易思考,无法想到另一个简单的(我所有的例子都指向复杂性)主题。
  • 哇!好的,这与我正在考虑的解决方案非常接近,但是我已将该构造函数和 __call 都放入一个特征中
  • 所以我的想法是,如果我想以这种方式调用Sedan,只需包含特征。否则我可以使用典型的装饰器调用方法。?这就像 Decorator 的反转。我称之为室内设计师。
  • 这是可以接受的做法吗? (即组合优于继承等)
  • 这个有一个名字:Delegation.
【解决方案2】:

这个例子是继承的完美例子。以下代码将完全按照您所说的去做。这里不需要特征或注入一些东西。 DEMO

<?php

class Car {
    public function paint () {
        echo " ________   \n";
        echo "/        \__\n";
        echo "|___________\\\n";
        echo "  O      O\n";
    }
}

class Sedan extends Car {

}

$sedan = new Sedan;
$sedan->paint();

【讨论】:

  • 这个例子的重点是展示如何在不使用继承的情况下正确完成。我听资深开发者说他们已经很多年没有使用继承了!
  • @DavidGraham:可以做到,但“正确”不适合这里。
猜你喜欢
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-26
  • 2020-11-08
  • 2011-04-14
相关资源
最近更新 更多