Определение методов класса в PHP
Это возможно в 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 есть поддержка черт. Trait - это реализация метода (ов), который не может быть создан как отдельный объект. Вместо этого можно использовать trait для расширения класса с помощью встроенной реализации. Узнайте больше о чертах здесь.
Да, можно добавить метод в класс 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);
Возможно, вы можете переопределить __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 или добавлять методы к классу во время выполнения, что примерно так близко, как вы собираетесь получить. В основном, это просто использование шаблонов проектирования для достижения той же функциональности. Zope 3 делает нечто похожее на эмуляцию миксинов в Python, другом языке, который не поддерживает их напрямую.