OUTSIDEPHP (as it is in C++)
を宣言することは可能ですか?class method
class definition?
8 に答える
いいえ、PHP5.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では、トレイトがサポートされています。トレイトは、スタンドアロンオブジェクトとしてインスタンス化できないメソッドの実装です。代わりに、トレイトを使用して、含まれている実装でクラスを拡張できます。特性の詳細については、こちらをご覧ください。
はい、定義後に PHP クラスにメソッドを追加することは可能です。「実験的な」拡張機能であるclasskitを使用したい。ただし、この拡張機能はデフォルトでは有効になっていないようです。そのため、カスタム PHP バイナリをコンパイルできるか、Windows の場合は 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をオーバーライドすることもできますが、コードを見つけて呼び出すための独自のシステムを作成する必要があります。たとえば、「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
private の場合、変数に格納されているクロージャーは$class->foo
それにアクセスできません。
いいえ。
ただし、それが役立つ場合は、以前に宣言されたクラスを拡張できます。
いいえ、それは不可能です。クラス構成の外部で関数/メソッドを定義すると、それはグローバル関数になります。
C++もこれを行うことはできません。宣言と定義を混同しましたか?
いいえ、誰もが言っているように、厳密には不可能です。
ただし、PHP で mixin をエミュレートしたり、実行時にメソッドをクラスに追加したりするために、このようなことを行うことができます。基本的に、同じ機能を実現するためにデザインパターンを使用しているだけです。Zope 3 は、ミックスインを直接サポートしていない別の言語である Python でミックスインをエミュレートするために、同様のことを行います。