Можно ли в PHP (as it is in C++) объявить class method ВНЕ class definition?
В C++ вы можете определять функции вне класса, и если первый параметр относится к этому типу класса, вы получаете то, что выглядит как перегрузка (т.е. явное «this»). Этот метод используется, например, для таких вещей, как оператор << в std :: cout. К сожалению, PHP не распознает тип при вызове функции. Количество параметров - это единственное, что можно использовать для различения функций PHP. Сама функция может проверять тип параметра и действовать с ним по-разному, но две функции с одинаковым именем и одинаковым количеством параметров в PHP недопустимы.






Нет.
Однако вы можете расширить ранее объявленные классы, если это поможет.
Нет, начиная с 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 - это реализация метода (ов), который не может быть создан как отдельный объект. Вместо этого трейт можно использовать для расширения класса с помощью вложенной реализации. Узнайте больше о Traits здесь.
Нет, это невозможно. если вы определяете функцию / метод вне конструкции класса, она становится глобальной функцией.
Все функции, определенные вне класса, не являются глобальными. Если вы сохраните функцию в переменной, то она не будет глобальной. ($func = function() {...};)
Возможно, вы могли бы переопределить __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);
}
}
}
C++ тоже не может этого сделать. Вы перепутали декларацию с deокончание?
Нет, как все говорили, это не совсем возможно.
Однако вы можете использовать что-то вроде этого, чтобы имитировать миксин в PHP или добавить методы в класс во время выполнения, что примерно настолько близко, насколько вы собираетесь получить. По сути, он просто использует шаблоны проектирования для достижения той же функциональности. Zope 3 делает что-то похожее на эмуляцию миксинов в Python, другом языке, который не поддерживает их напрямую.
Ваше утверждение о Python неверно, поскольку Python поддерживает множественное наследование и действительно поддерживает определение методов во время выполнения.
Да, можно добавить метод в класс PHP после его определения. Вы хотите использовать классный набор, которое является «экспериментальным» расширением. Однако похоже, что это расширение не включено по умолчанию, поэтому это зависит от того, можете ли вы скомпилировать собственный двоичный файл PHP или загрузить библиотеки DLL PHP, если в 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);
Обратите внимание, что для этого требуется расширение PECL, которое не у всех автоматически устанавливается на своем сервере. Кроме того, теперь он называется runkit. php.net/manual/en/function.runkit-method-add.php
Поскольку 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, не могло бы получить к нему доступ.
Обратите внимание, что использование & при вызове функции в PHP запрещено. Некоторое время назад он был принят (вероятно, необходим в PHP 4), но сегодня вы получаете предупреждения или ошибки при запуске этого кода call_user_func($class->foo, &$class, 2);.
Я знаю. Это было необходимо раньше
Более того, в последних версиях PHP вы можете использовать $ this в замыканиях.
Насколько я знаю, то, что вы спрашиваете, невозможно на С ++. Возможно, вы захотите уточнить.