Возможно ли в PHP (as it is in C++)
объявить class method
OUTSIDE class definition?
Нет, начиная с PHP 5.2. Тем не менее, вы можете использовать метод __call
magic для переадресации вызова произвольной функции или метода.
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 – это реализация метода (методов), который не может быть создан как отдельный объект. Вместо этого, черта может использоваться для расширения класса с сохраненной реализацией. Подробнее читайте здесь .
Да, после его определения можно добавить метод в класс PHP. Вы хотите использовать classkit , который является «экспериментальным» расширением. По-видимому, это расширение не включено по умолчанию, однако, это зависит от того, можно ли скомпилировать пользовательский 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, чтобы найти отсутствующий метод во время выполнения, но вам нужно будет создать свою собственную систему для поиска и вызова кода. Например, вы можете загрузить класс «Делегат» для обработки вызова метода.
Вот пример: если вы попытались вызвать $ 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
magic:
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
не получило бы доступа к нему.
Нет, это невозможно. если вы определяете функцию / метод вне класса, она становится глобальной функцией.
C ++ тоже не может этого сделать. Вы смешивали декларацию с дефиницией ?
Нет, как говорили все, это не совсем возможно.
Однако вы можете сделать что-то подобное, чтобы эмулировать mixin в PHP или добавлять методы в класс во время выполнения, что примерно так же близко, как вы собираетесь получить. В основном, это просто использование шаблонов проектирования для достижения той же функциональности. Zope 3 делает что-то похожее на эмуляцию mixins в Python, другой язык, который не поддерживает их напрямую.