Php 基于条件的继承?

Php 基于条件的继承?,php,inheritance,Php,Inheritance,我试图继承一组不同的父类,甚至不继承任何类,但根据某些条件。 例如,下面是我想做的 $choice = 2; switch($choice) { case 1: class child extends parent1 break; case 2: class child extends parent2 break; default: class child

我试图继承一组不同的父类,甚至不继承任何类,但根据某些条件。 例如,下面是我想做的

$choice = 2;
switch($choice) {
     case 1: 
         class child extends parent1
         break;
     case 2: 
         class child extends parent2
         break;
     default:
         class child 
         //extend nothing
         break;
    }
我想你能明白我在这里想要达到什么

父类

class car { }
儿童班

class ferari extends car { }
class ford extends car { }
孙子班

class automaticcar { }
class manualcar { }
现在,这个grandclasses需要使用post根据表单发送的值插入父类。像这样的

$brand = $_POST['brand'];

if(isset($brand) && !empty($brand)) {
  class automaticcar extends $brand 
}
else {
  class automaticcar extends car  //or even nothing
}
//然后我想写clas的剩余部分
s

您的问题“基于条件的继承好吗?”是的,在许多情况下它看起来是必要的。但我认为最好是有条件地启动对象,而不是在条件中定义扩展类

更新
据我所知,您希望根据条件拥有子类的不同属性/函数。我在项目中遇到了类似的需求/问题。在那里,它与视图逻辑有关。你可以查一下

如果我正确理解了您的问题,那么您应该在单独的php文件中预先准备好子类,如下所示:-

child1类

class1 child extends parent1
class2 child extends parent2
儿童2级

class1 child extends parent1
class2 child extends parent2
在条件部分,执行以下操作:-

$choice = 2;
switch($choice) {
     case 1: 
         include /path/to/child1;
         $obj = new child1();
         break;
     case 2: 
         include /path/to/child2;
         $obj = new child2();
         break;
     default:
         include /path/to/child;
         $obj = new child();
         //extend nothing
         break;
    }
你的问题是“基于条件的继承好吗?”那么是的,在许多情况下它看起来是必要的。但我认为最好是有条件地启动对象,而不是在条件中定义扩展类

更新
据我所知,您希望根据条件拥有子类的不同属性/函数。我在项目中遇到了类似的需求/问题。在那里,它与视图逻辑有关。你可以查一下

如果我正确理解了您的问题,那么您应该在单独的php文件中预先准备好子类,如下所示:-

child1类

class1 child extends parent1
class2 child extends parent2
儿童2级

class1 child extends parent1
class2 child extends parent2
在条件部分,执行以下操作:-

$choice = 2;
switch($choice) {
     case 1: 
         include /path/to/child1;
         $obj = new child1();
         break;
     case 2: 
         include /path/to/child2;
         $obj = new child2();
         break;
     default:
         include /path/to/child;
         $obj = new child();
         //extend nothing
         break;
    }

使用基于类的继承语言无法实现您试图获得的继承类型

您可以获得的更接近的解决方案是使用一种装饰器模式和一些神奇的方法。大概是这样的:

$choice = 2;
switch($choice) {
     case 1: 
         $obj = new child(new parent1());
         break;
     case 2: 
         $obj = new child(new  parent2());
         break;
     default:
         //extend nothing
         $obj = new child();
         break;
    }
儿童与此相似:

class child {
    function __construct($composeObj) {
        $this->core = $composeObj;
        // wathever you need to iniyialize
    }
    function __call($name, $params) {
        return call_user_func(array($sthis->core, $name), $parameters);
    }
    // other functions
} // eo child
此解决方案有一些警告,但如果您能够解决这些问题(对象不属于合成对象的族,call_user_func不通过引用传递参数),则这是一个合适的解决方案


一个更好的解决方案是Sandepan建议的工厂方法,但你已经拒绝了

使用基于类的继承语言无法获得您试图获得的继承类型

您可以获得的更接近的解决方案是使用一种装饰器模式和一些神奇的方法。大概是这样的:

$choice = 2;
switch($choice) {
     case 1: 
         $obj = new child(new parent1());
         break;
     case 2: 
         $obj = new child(new  parent2());
         break;
     default:
         //extend nothing
         $obj = new child();
         break;
    }
儿童与此相似:

class child {
    function __construct($composeObj) {
        $this->core = $composeObj;
        // wathever you need to iniyialize
    }
    function __call($name, $params) {
        return call_user_func(array($sthis->core, $name), $parameters);
    }
    // other functions
} // eo child
此解决方案有一些警告,但如果您能够解决这些问题(对象不属于合成对象的族,call_user_func不通过引用传递参数),则这是一个合适的解决方案


一个更好的解决方案是Sandepan建议的工厂方法,但你已经拒绝了

法拉利与福特在性能或方法上没有什么不同。他们都还是汽车。它们的属性只有不同的值。创建一个特殊化的子类应该是没有必要的。相反,请尝试以下路线:

class Car
{
    protected $_manufacturer;
    protected $_engine;
    protected $_gear;
    protected $_price;
    protected $_color;

    public function __construct($manufacturer, $engine, $gear, $price, $color)
    {
        // setting properties
    }
}

class CarFactory
{
    public static function createFerrari()
    {
        $engine = new Engine(500); // PS
        $gear = new Gear(6, 'manual');
        return new Car('Ferrari', $engine, $gear, '250000', 'red');
    }

    public static function createFord()
    {
        $engine = new Engine(90); // PS
        $gear = new Gear(5, 'automatic');
        return new Car('Ford', $engine, $gear, '50000', 'black');
    }

    // other car creation methods ...
}

如果您扩展了一个类,那么您正在创建一个is-a关系。子类是一个专门的父类。齿轮和发动机不是什么汽车,而是汽车所拥有的东西。无论何时,只要你能描述一个类有什么东西,它就是它自己的类的候选者,或者仅仅是一个属性。它是否应该属于自己的类别取决于它是否拥有独特的状态和责任。

法拉利与福特在提供的性能或方法上没有什么不同。他们都还是汽车。它们的属性只有不同的值。创建一个特殊化的子类应该是没有必要的。相反,请尝试以下路线:

class Car
{
    protected $_manufacturer;
    protected $_engine;
    protected $_gear;
    protected $_price;
    protected $_color;

    public function __construct($manufacturer, $engine, $gear, $price, $color)
    {
        // setting properties
    }
}

class CarFactory
{
    public static function createFerrari()
    {
        $engine = new Engine(500); // PS
        $gear = new Gear(6, 'manual');
        return new Car('Ferrari', $engine, $gear, '250000', 'red');
    }

    public static function createFord()
    {
        $engine = new Engine(90); // PS
        $gear = new Gear(5, 'automatic');
        return new Car('Ford', $engine, $gear, '50000', 'black');
    }

    // other car creation methods ...
}

如果您扩展了一个类,那么您正在创建一个is-a关系。子类是一个专门的父类。齿轮和发动机不是什么汽车,而是汽车所拥有的东西。无论何时,只要你能描述一个类有什么东西,它就是它自己的类的候选者,或者仅仅是一个属性。它是否应该是它自己的类取决于封装的东西是否有自己独特的状态和责任。

首先,我真的认为您对面向对象的原则理解不够,无法要求提供此功能。PHP实现的OOP风格并不真正需要它

您正在请求类似条件混合的内容。实现它是可能的,但这是一个巨大的难题,应该避免。这是我不久前在测试一些概念时总结的一些东西:

<?php
    class Mixin
    {
        private $objects = array();
        private $funcs = array();

        public function addMixin(Mixable $object)
        {
            $exported_vars = $object->exportVars();
            foreach ($exported_vars as $key => &$ref)
                $this->$key = &$ref;

            $vars = array();
            foreach (array_keys(get_object_vars($this)) as $key)
                $vars[$key] = &$this->$key;
            $object->importVars($vars);

            $this->objects[] = $object;
        }

        public function __call($method, $args)
        {
            if (!isset($this->funcs[$method]))
            {
                $found = false;
                foreach ($this->objects as $obj)
                {
                    if (method_exists($obj, $method))
                    {
                        $found = true;
                        $this->funcs[$method] = array($obj, $method);
                        break;
                    }
                }

                if (!$found)
                    throw new Exception("method doesn't exist");
            }

            return call_user_func_array($this->funcs[$method], $args);
        }
    }

    class Mixable
    {
        public function exportVars()
        {
            $vars = array();

            foreach (array_keys(get_object_vars($this)) as $key)
            {
                $vars[$key] = &$this->$key;
            }

            return $vars;
        }

        public function importVars($vars)
        {
            foreach ($vars as $key => &$ref)
            {
                $this->$key = &$ref;
            }
        }
    }
?>

首先,我真的认为您对面向对象原则的理解还不够透彻,无法要求提供此功能。PHP实现的OOP风格并不真正需要它

您正在请求类似条件混合的内容。实现它是可能的,但这是一个巨大的难题,应该避免。这是我不久前在测试一些概念时总结的一些东西:

<?php
    class Mixin
    {
        private $objects = array();
        private $funcs = array();

        public function addMixin(Mixable $object)
        {
            $exported_vars = $object->exportVars();
            foreach ($exported_vars as $key => &$ref)
                $this->$key = &$ref;

            $vars = array();
            foreach (array_keys(get_object_vars($this)) as $key)
                $vars[$key] = &$this->$key;
            $object->importVars($vars);

            $this->objects[] = $object;
        }

        public function __call($method, $args)
        {
            if (!isset($this->funcs[$method]))
            {
                $found = false;
                foreach ($this->objects as $obj)
                {
                    if (method_exists($obj, $method))
                    {
                        $found = true;
                        $this->funcs[$method] = array($obj, $method);
                        break;
                    }
                }

                if (!$found)
                    throw new Exception("method doesn't exist");
            }

            return call_user_func_array($this->funcs[$method], $args);
        }
    }

    class Mixable
    {
        public function exportVars()
        {
            $vars = array();

            foreach (array_keys(get_object_vars($this)) as $key)
            {
                $vars[$key] = &$this->$key;
            }

            return $vars;
        }

        public function importVars($vars)
        {
            foreach ($vars as $key => &$ref)
            {
                $this->$key = &$ref;
            }
        }
    }
?>

我知道我差不多晚了六年。但为了防止有人再次降落在这里,我决定把它放在这里

请注意,我并不认为类名称
Car
ferari
Ford
等是车辆。以便能够以通用方式应用此模式

我将按偏好的降序使用以下方法之一:

  • 类别名
    (PHP5>=5.3.0,PHP7)

  • 继承的条件堆叠(太多)