我试图继承一组不同的父类,甚至不继承任何类,但是根据某些条件。 例如,这就是我想做的事情
$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 { }
现在这个大班需要根据使用post从表单发送的值来插入父类。像这样的东西
$brand = $_POST['brand'];
if(isset($brand) && !empty($brand)) {
class automaticcar extends $brand
}
else {
class automaticcar extends car //or even nothing
}
//And then I wish to write the remaining portion of the clas
Š
答案 0 :(得分:5)
使用继承基于类的语言无法实现您尝试获取的继承类型。
你可以获得更接近的解决方案是使用一种装饰模式和一些魔术方法。像这样的东西:
$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不通过引用传递参数)这是一个合适的解决方案。
更好的解决方案是sandeepan建议的工厂方法,但你已经拒绝了它。
答案 1 :(得分:1)
法拉利在其提供的属性或方法方面与福特没有什么不同。他们都是汽车。它们的属性只有不同的值。不需要创建一个特殊化的子类。而是尝试这条路线:
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 关系。子类是一个专门的父类。齿轮和发动机不是汽车 ,而是汽车拥有的东西。每当你能够描述一个类来拥有某个东西时,它就是它自己的类的候选者或仅仅是一个属性。它是否属于自己的类取决于封装的东西是否具有独特的状态和责任。
答案 2 :(得分:0)
您的问题是“基于条件的继承是否良好?”然后是的,在许多情况下看来是必要的。但我认为有条件地启动对象而不是在条件内定义扩展类会更好。
<强>更新强>
据我所知,你希望根据条件拥有子类的不同属性/功能。我在项目中遇到了类似的需求/问题。它与视图逻辑有关。您可以查看How is my approach to reuse view logic in my project?
如果我理解你的问题,那么你应该事先准备好这些子类,就像在单独的php文件中一样: -
child1 class
class1 child extends parent1
child2 class
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;
}
答案 3 :(得分:0)
首先,我真的不认为你理解面向对象的原则就足以要求这个功能了。使用PHP实现的OOP风格并不是真的需要它。
您正在请求条件混合等内容。它可以实现它,但它是一个巨大的kludge,应该避免。这是我刚刚在测试一些概念时放在一起的东西:
<?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
class Parent1 extends Mixable
{
protected $name = 'Parent 1';
public function p1()
{
print "P1\n";
}
}
class Parent2 extends Mixable
{
protected $name = 'Parent 2';
public function p2()
{
print "P2\n";
}
}
class Child1 extends Mixin
{
public function whoAmI()
{
print $this->name."\n";
}
}
$foo = new Child1();
if (mt_rand(1, 2) == 1)
{
$foo->addMixin(new Parent1());
$foo->p1();
}
else
{
$foo->addMixin(new Parent2());
$foo->p2();
}
$foo->whoAmI();
?>
请不要尝试使用该代码!即使它已经准备就绪,这也是一个糟糕的概念。我把它放在这里向你展示 的工作原理。
我认为你真正应该做的就是更像工厂模式:构建一个CarFactory
类,返回一个正确的子类Car
。 (或者您可以在Car
类中创建工厂方法。)
可能类似于Car::get($_POST['brand'])
。
答案 4 :(得分:0)
我知道我差不多六年了。但是为了以防有人再次降落在这里,我决定把它放在这里。
请注意,我并不假设隐含的理解是类名Car
,Ferrari
,Ford
等是车辆。以便能够以通用的方式应用这种模式。
我将按优先顺序递减使用以下任一方法:
类别名 PHP Manual (PHP 5 >= 5.3.0, PHP 7)
// Assuming $my_brand is the required brand
if (!class_exists($my_brand))
{
// Raise suitable warning here and exit
exit('Brand ' . $my_brand . 'not found.');
}
class_alias($my_brand, 'MyBrand');
class AutomaticCar extends MyBrand
{
}
继承的条件堆叠(工作量太大,但在较大规模的项目中很有用)
// File: lib/MyBrand/Ferrari.php
class MyBrand extends Ferrari
{
}
// File: lib/MyBrand/Ford.php
class MyBrand extends Ford
{
}
// Then in your main code, assuming $my_brand is the required brand
if (!file_exists('lib/MyBrand/' . $my_brand . '.php'))
{
// Raise suitable warning here and exit
exit('Brand ' . $my_brand . 'not found.');
}
class AutomaticCar extends MyBrand
{
}
我现在可以使用的其他模式(例如工厂设计和装饰模式)会考虑采用不符合确切主题的不同路线。所以这就是现在。