我知道你可以像下面的构造,当它扩展类:
class b extends a {
}
但是,它可能从脚本动态地扩展类? 如:
$b = new b($input) extends a;
我希望做到的是要differnetly扩展模块wheither它在管理员的使用,而不是公共页面。 我知道我可以用同样的名称创建两个不同的父类,只包括按照管理或公共之一。 但我的问题是,是否可以动态地做到这一点在PHP?
我知道你可以像下面的构造,当它扩展类:
class b extends a {
}
但是,它可能从脚本动态地扩展类? 如:
$b = new b($input) extends a;
我希望做到的是要differnetly扩展模块wheither它在管理员的使用,而不是公共页面。 我知道我可以用同样的名称创建两个不同的父类,只包括按照管理或公共之一。 但我的问题是,是否可以动态地做到这一点在PHP?
你不能,但是这已经要求了几年: https://bugs.php.net/bug.php?id=41856&edit=1
你可以一个eval中定义的类,但它比正常声明类更多的麻烦。
不,不是没有像RunKit的延伸。
你可能会考虑一种替代方法。 如果你想B到承担的功能,也许像下面这样可以提供一种“混入”的方法。 总体情况是,不是B为A,B代表小时候A.
<?php
class MixMeIn
{
public $favouriteNumber = 7;
public function sayHi() {
echo "Hello\n";
}
}
class BoringClass
{
private $mixins = array();
public function mixin($object)
{
$this->mixins[] = $object;
}
public function doNothing() {
echo "Zzz\n";
}
public function __call($method, $args)
{
foreach ($this->mixins as $mixin)
{
if (method_exists($mixin, $method))
{
return call_user_func_array(array($mixin, $method), $args);
}
}
throw new Exception(__CLASS__ + " has no method " + $method);
}
public function __get($attr)
{
foreach ($this->mixins as $mixin)
{
if (property_exists($mixin, $attr))
{
return $mixin->$attr;
}
}
throw new Exception(__CLASS__ + " has no property " + $attr);
}
public function __set($attr, $value)
{
foreach ($this->mixins as $mixin)
{
if (property_exists($mixin, $attr))
{
return $mixin->$attr = $value;
}
}
throw new Exception(__CLASS__ + " has no property " + $attr);
}
}
// testing
$boring = new BoringClass();
$boring->doNothing();
try {
$boring->sayHi(); // not available :-(
}
catch (Exception $e) {
echo "sayHi didn't work: ", $e->getMessage(), "\n";
}
// now we mixin the fun stuff!
$boring->mixin(new MixMeIn());
$boring->sayHi(); // works! :-)
echo $boring->favouriteNumber;
只是滑稽的想法。 我希望我理解正确的问题。
但你不能使用extends
的同时创建对象。 extends
只在类定义的使用和定义了其他类是“父”我们的新类。
另外,如果你是舒服的JavaScript风格的继承,不介意失去类型检查:
<? //PHP 5.4+
final class ExpandoLookalike {
//Allow callable properties to be executed
public function __call($name, $arguments) {
\call_user_func_array($this->$name, $arguments);
}
}
$newBaseModule = static function(){
$base = new ExpandoLookalike();
//Common base functions get assigned here.
$basePrivateVar = 42;
$base->commonFunction = static function($params1, $params2) use ($basePrivateVar){
echo "common function\n";
};
$base->comment = static function() use ($basePrivateVar){
echo "Doing base comment with $basePrivateVar\n";
};
return $base;
};
//Javascript-style extends
$newAdminModule = static function($param) use ($newBaseModule){
$base = $newBaseModule();
$privateVar = 5;
$base->adminProperty = 60;
$base->suspendSite = static function() use ($param, $privateVar){
echo 'Doing admin only function ';
echo "with $param, $privateVar\n";
};
return $base;
};
$newPublicModule = static function() use ($newBaseModule){
$base = $newBaseModule();
$privateVar = 3;
//Javascript-style overloading
$oldComment = $base->comment;
$base->comment = static function($data) use ($oldComment, $privateVar){
$oldComment();
echo 'Doing public function ';
echo "with $data\n";
};
return $base;
};
$baseModule = $newBaseModule();
$adminModule = $newAdminModule('P');
$publicModule = $newPublicModule();
$adminModule->suspendSite(); //echos 'Doing admin only function with P, 5'
echo "{$adminModule->adminProperty}\n"; //echos '60'
$publicModule->comment('com'); //echos 'Doing base comment with 42'
//'Doing public function with com'
?>
尽管关闭大门,特点和接口,它开辟了其他有趣的大门,以补偿:
<? //PHP 5.4+
$inheritAllTheThings = static function(){
$base = new ExpandoLookalike();
foreach(\func_get_args() as $object){
foreach($object as $key => $value){
//Properties from later objects overwrite properties from earlier ones.
$base->$key = $value;
}
}
return $base;
};
$allOfEm = $inheritAllTheThings(
$newPublicModule(),
$newAdminModule('Q'),
['anotherProp' => 69,]
);
$allOfEm->comment('f'); //echos 'Doing base comment with 42'
//Because AdminModule came after PublicModule, the function that echos 'f'
//from PublicModule was overridden by the function from AdminModule.
//Hence, order denotes resolutions for multiple inheritance collisions.
$allOfEm->suspendSite(); //echos 'Doing admin only function with Q, 5'
echo $allOfEm->anotherProp . "\n"; //echos '69'
?>
你可以用强制类型转换。 如果延伸B,则你可以做
$a=(a)(new b($input));
这是不完全一样,但大同小异。
你可以看一下: https://github.com/ptrofimov/jslikeobject
作者实现JS状物体与支持继承。
但也许它不是那么好就用这样的对象,而不是通常的。
是的,作为科里提到,这个功能已经被要求之前。 但在此之前,你可以创建一个解决方法。 这是我的老同学把戏此
创建两个单独的类像这样的:
class a {
}
class b {
public $object;
}
然后,也创建一个扩展版
class bextendeda extends a {
}
在B类的构造方法中,放置几个函数如果被请求其重定向到所述扩展对象。
class b {
public $object;
public function __contruct($extend = false) {
if($extend) $this -> object = new bextendeda();
else $this -> object = $this;
}
function __get($prop) {
return $this-> object -> $prop;
}
function __set($prop, $val) {
$this-> object -> $prop = $val;
}
function __call($name, $arguments)
{
return call_user_func_array(array($this -> object, $name), $arguments);
}
}
有你有它 ,如果你想扩展版本,只是这样做
$b = new b(true);
如果不
$b = new b();
请享用 :)