Определение методов класса в PHP - PullRequest
7 голосов
/ 16 сентября 2008

Возможно ли в PHP (as it is in C++) объявить class method ВНЕ class definition?

Ответы [ 8 ]

9 голосов
/ 16 сентября 2008

Нет, с 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 для расширения класса с помощью встроенной реализации. Подробнее о Чертах здесь .

5 голосов
/ 12 августа 2009

Да, можно добавить метод в класс 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);
3 голосов
/ 16 сентября 2008

Возможно, вы можете переопределить __ 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);
        }


    }

}
1 голос
/ 05 ноября 2011

Поскольку 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 не сможет получить к нему доступ.

1 голос
/ 16 сентября 2008

Нет.

Вы можете расширить ранее объявленные классы, если это поможет.

0 голосов
/ 16 сентября 2008

Нет, как все говорили, это не строго возможно.

Однако вы можете сделать что-то вроде этого , чтобы эмулировать миксин в PHP или добавлять методы к классу во время выполнения, что примерно так близко, как вы собираетесь получить. В основном, это просто использование шаблонов проектирования для достижения той же функциональности. Zope 3 делает нечто похожее на эмуляцию миксинов в Python, другом языке, который не поддерживает их напрямую.

0 голосов
/ 16 сентября 2008

C ++ тоже не может этого сделать. Вы перепутали декларацию с де окончанием ?

0 голосов
/ 16 сентября 2008

Нет, это не возможно. если вы определяете функцию / метод вне конструкции класса, она становится глобальной функцией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...