是否可以在OUTSIDE中PHP (as it is in C++)
声明class method
class definition?
8 回答
不,从 PHP 5.2 开始。但是,您可以使用__call
魔术方法将调用转发到任意函数或方法。
class A {
public function __call($method, $args) {
if ($method == 'foo') {
return call_user_func_array('bar', $args);
}
}
}
function bar($x) {
echo $x;
}
$a = new A();
$a->foo('12345'); // will result in calling bar('12345')
在 PHP 5.4 中支持traits。Trait 是不能作为独立对象实例化的方法的实现。相反,特征可用于扩展具有包含实现的类。在此处了解有关特征的更多信息。
是的,可以在定义 PHP 类后添加一个方法。您想使用classkit,这是一个“实验性”扩展。但是,默认情况下似乎未启用此扩展,因此这取决于您是否可以在 Windows 上编译自定义 PHP 二进制文件或加载 PHP DLL(例如 Dreamhost 确实允许自定义 PHP 二进制文件,并且它们很容易设置)。
<?php
class A { }
classkit_method_add('A', 'bar', '$message', 'echo $message;',
CLASSKIT_ACC_PUBLIC);
$a = new A();
$a->bar('Hello world!');
PHP手册中的示例:
<?php
class Example {
function foo() {
echo "foo!\n";
}
}
// create an Example object
$e = new Example();
// Add a new public method
classkit_method_add(
'Example',
'add',
'$num1, $num2',
'return $num1 + $num2;',
CLASSKIT_ACC_PUBLIC
);
// add 12 + 4
echo $e->add(12, 4);
您也许可以覆盖__call 或 __callStatic以在运行时定位丢失的方法,但您必须构建自己的系统来定位和调用代码。例如,您可以加载“Delegate”类来处理方法调用。
下面是一个例子——如果你试图调用$foo->bar(),这个类会试图创建一个FooDelegate_bar 类,并用相同的参数调用它的bar()。如果您设置了类自动加载,则委托可以保存在单独的文件中,直到需要...
class Foo {
public function __call($method, $args) {
$delegate="FooDelegate_".$method;
if (class_exists($delegate))
{
$handler=new $delegate($this);
return call_user_func_array(array(&$handler, $method), $args);
}
}
}
由于 PHP 5.3 支持闭包,您可以将实例方法动态定义为持有闭包的变量:
$class->foo = function (&$self, $n) {
print "Current \$var: " . $self->var . "\n";
$self->var += $n;
print "New \$var: " .$self->var . "\n";
};
以$self
(不能使用$this
外部对象上下文)作为参考(&
),您可以修改实例。
但是,当您尝试正常调用该函数时会出现问题:
$class->foo(2);
你得到一个致命的错误。由于语法,PHP 认为foo
是一种方法。$class
此外,您必须将实例作为第一个参数传递。
幸运的是,有一个特殊的函数可以按名称调用函数call_user_func
:
call_user_func($class->foo, &$class, 2);
# => Current $var: 0
# => New $var: 2
只要记住放在&
实例变量之前。
如果您使用__call
魔术方法,则更容易:
class MyClass {
public function __call ($method, $arguments) {
if (isset($this->$method)) {
call_user_func_array($this->$method, array_merge(array(&$this), $arguments));
}
}
}
现在你可以打电话$class->foo(2)
了。魔术__call
方法捕获对未知方法的调用,并调用$class->foo
与被调用方法同名的变量中的闭包。
当然,如果$class->var
是私有的,存储在$class->foo
变量中的闭包将无法访问它。
不。
但是,如果有帮助,您可以扩展先前声明的类。
不,这是不可能的。如果您在类构造之外定义函数/方法,它将成为全局函数。
C++ 也无法做到这一点。您是否将声明与定义混淆了?
不,正如大家所说,严格来说不可能。
但是,您可以执行类似的操作来模拟 PHP 中的 mixin 或在运行时将方法添加到类中,这与您将获得的差不多。基本上,它只是使用设计模式来实现相同的功能。Zope 3 做了类似于在 Python 中模拟 mixins 的事情,Python 是另一种不直接支持它们的语言。