在PHP中定义类方法

时间:2008-09-16 11:46:15

标签: php class

PHP (as it is in C++)是否可以在class method

之外宣布class definition? OUTSIDE

8 个答案:

答案 0 :(得分: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是一种方法的实现,无法将其实例化为独立对象。相反,trait可用于扩展具有包含实现的类。详细了解Traits here

答案 1 :(得分:5)

是的,可以在定义PHP类后添加方法。您想使用classkit,这是一个“实验性”扩展程序。看来默认情况下没有启用此扩展,因此它取决于您是否可以编译自定义PHP二进制文件或加载PHP DLL(如果在Windows上)(例如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);

答案 2 :(得分:3)

您可以覆盖__call or __callStatic以在运行时找到缺少的方法,但您必须组建自己的系统来查找和调用代码。例如,您可以加载“Delegate”类来处理方法调用。

这是一个例子 - 如果你试图调用$ foo-&gt; 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);
        }


    }

}

答案 3 :(得分:1)

没有。

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

答案 4 :(得分:1)

由于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)了。 magic __call方法捕获对未知方法的调用,并调用$class->foo变量中的闭包,其名称与被调用方法的名称相同。

当然,如果$class->var是私有的,那么存储在$class->foo变量中的闭包将无法访问它。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

C ++也不能这样做。您是否将声明与de finition混合

答案 7 :(得分:0)

不,正如大家所说,这不是严格可能的。

但是,您可以something like this在PHP中模拟mixin,或者在运行时向类添加方法,这与您将要获得的一样接近。基本上,它只是使用设计模式来实现相同的功能。 Zope 3做的类似于在Python中模拟mixins,另一种语言不直接支持它们。