7

是否可以在OUTSIDE中PHP (as it is in C++)声明class methodclass definition?

4

8 回答 8

9

不,从 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 是不能作为独立对象实例化的方法的实现。相反,特征可用于扩展具有包含实现的类。在此处了解有关特征的更多信息。

于 2008-09-16T11:59:55.937 回答
6

是的,可以在定义 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);
于 2009-08-12T16:23:08.880 回答
3

您也许可以覆盖__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);
        }


    }

}
于 2008-09-16T12:01:09.523 回答
2

由于 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变量中的闭包将无法访问它。

于 2011-11-05T13:28:05.513 回答
1

不。

但是,如果有帮助,您可以扩展先前声明的类。

于 2008-09-16T11:51:11.637 回答
0

不,这是不可能的。如果您在类构造之外定义函数/方法,它将成为全局函数。

于 2008-09-16T12:00:33.660 回答
0

C++ 也无法做到这一点。您是否将声明与定义混淆了?

于 2008-09-16T12:02:24.700 回答
0

不,正如大家所说,严格来说不可能。

但是,您可以执行类似的操作来模拟 PHP 中的 mixin 或在运行时将方法添加到类中,这与您将获得的差不多。基本上,它只是使用设计模式来实现相同的功能。Zope 3 做了类似于在 Python 中模拟 mixins 的事情,Python 是另一种不直接支持它们的语言。

于 2008-09-16T12:13:16.030 回答