Last active
September 21, 2020 10:12
-
-
Save monmonmon/6922871 to your computer and use it in GitHub Desktop.
Trait が導入される php5.4 より前の php で mixin 的なことを実装してみた。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// mixin クラス | |
class MixinClass | |
{ | |
// インスタンスメソッド(引数あり) | |
// 注:第1引数に、mixin 先のクラスのインスタンスを表す "$that" が必要です。 | |
// 実際呼ぶ時は ->mixin_instance_method($message) ってなります。 | |
public function mixin_instance_method($that, $message, DateTime $date) | |
{ | |
print "これは MixinClass のインスタンスメソッドです $message ".$date->format('Y-m-d')."\n"; | |
print "Foo の public メンバ変数にアクセスすることも出来ます。 ".$that->foooooo."\n"; | |
} | |
// 静的メソッド(引数あり) | |
public static function mixin_static_method($message, DateTime $date) | |
{ | |
print "これは MixinClass の静的メソッドです $message ".$date->format('Y-m-d')."\n"; | |
} | |
} | |
// mixin クラスその2。mixin するクラスが複数になってもいけます | |
class MixinClass2 | |
{ | |
// インスタンスメソッド(引数なし) | |
// 注:引数なしのメソッドでも第1引数に "$that" は必要です。 | |
// 実際呼ぶ時は ->mixin2_instance_method() こーなります。 | |
public function mixin2_instance_method($that) | |
{ | |
print "これは MixinClass2 のインスタンスメソッドです\n"; | |
} | |
// 静的メソッド(引数なし) | |
public static function mixin2_static_method() | |
{ | |
print "これは MixinClass2 の静的メソッドです\n"; | |
} | |
} | |
// 親クラス | |
class Bar | |
{ | |
// 親クラス Bar のインスタンスメソッド | |
public function parent_instance_method() | |
{ | |
print "これは親クラス Bar のインスタンスメソッドです\n"; | |
} | |
// 親クラス Bar の静的メソッド | |
public static function parent_static_method() | |
{ | |
print "これは親クラス Bar の静的メソッドです\n"; | |
} | |
} | |
// mixin 対象クラス | |
class Foo extends Bar | |
{ | |
public $foooooo = 999; | |
// コンストラクタで MixinClass, MixinClass2 のインスタンスを作っときます | |
public function __construct() | |
{ | |
$this->mixin1 = new MixinClass(); | |
$this->mixin2 = new MixinClass2(); | |
} | |
// __call をオーバーライドして、インスタンスメソッドの mixin を実装します | |
// インスタンスメソッド $method_name がこのクラスでも先祖クラスでも未定義な場合、ここへ到達。 | |
public function __call($method_name, $args) | |
{ | |
// Foo 自身を表す $this を引数の先頭に追加します | |
array_unshift($args, $this); | |
if (is_callable(array(&$this->mixin1, $method_name))) { | |
// MixinClass#$method_name を実行 | |
return call_user_func_array(array(&$this->mixin1, $method_name), $args); | |
} elseif (is_callable(array(&$this->mixin2, $method_name))) { | |
// MixinClass2#$method_name を実行 | |
return call_user_func_array(array(&$this->mixin2, $method_name), $args); | |
} else { | |
throw new BadMethodCallException(); | |
} | |
} | |
// __callStatic (php5.3.0 以降) をオーバーライドして、静的メソッドの mixin を実装します | |
// 静的メソッド $method_name がこのクラスでも先祖クラスでも未定義な場合、ここへ到達。 | |
public static function __callStatic($method_name, $args) | |
{ | |
if (is_callable("MixinClass::$method_name")) { | |
// MixinClass::$method_name を実行 | |
return call_user_func_array("MixinClass::$method_name", $args); | |
} elseif (is_callable("MixinClass2::$method_name")) { | |
// MixinClass2::$method_name を実行 | |
return call_user_func_array("MixinClass2::$method_name", $args); | |
} else { | |
throw new BadMethodCallException(); | |
} | |
} | |
// Foo 自身のインスタンスメソッド | |
public function instance_method() | |
{ | |
print "これは Foo 自身のインスタンスメソッドです\n"; | |
} | |
// Foo 自身の静的メソッド | |
public static function static_method() | |
{ | |
print "これは Foo 自身の静的メソッドです\n"; | |
} | |
} | |
// Foo クラスのインスタンスを生成 | |
$foo = new Foo(); | |
//-------------------------------------------------- | |
// 1. まずはインスタンスメソッドの mixin を実験 | |
// MixinClass から mixin された mixin_instance_method() を呼んでみる | |
print "// \$foo->mixin_instance_method\n"; | |
$foo->mixin_instance_method("yahoooooo!", new DateTime()); | |
print "\n"; | |
// MixinClass2 から mixin された mixin2_instance_method() を呼んでみる | |
print "// \$foo->mixin2_instance_method\n"; | |
$foo->mixin2_instance_method(); | |
print "\n"; | |
// Foo 自身のインスタンスメソッドを呼んでみる | |
print "// \$foo->instance_method\n"; | |
$foo->instance_method(); | |
print "\n"; | |
// 親クラス Bar のインスタンスメソッドも呼んでみる | |
print "// \$foo->parent_instance_method\n"; | |
$foo->parent_instance_method(); | |
print "\n"; | |
//-------------------------------------------------- | |
// 2. 次に静的メソッドの mixin も実験 | |
// MixinClass から mixin された mixin_static_method() を呼んでみる | |
print "// Foo::mixin_static_method\n"; | |
Foo::mixin_static_method("yahoooooo!", new DateTime()); | |
print "\n"; | |
// MixinClass2 から mixin された mixin2_static_method() を呼んでみる | |
print "// Foo::mixin2_static_method\n"; | |
Foo::mixin2_static_method(); | |
print "\n"; | |
// Foo 自身の静的メソッドを呼んでみる | |
print "// Foo::static_method\n"; | |
Foo::static_method(); | |
print "\n"; | |
// 親クラス Bar の静的メソッドも呼んでみる | |
print "// Foo::parent_static_method\n"; | |
Foo::parent_static_method(); | |
print "\n"; | |
//-------------------------------------------------- | |
// 3. いいね! | |
print <<<IINE | |
* * | |
* + | |
n ∧_∧ n IINE! | |
+ (ヨ(* ´∀`)E) | |
Y Y * | |
IINE; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment