ゆうなんとかさんの雑記帳的な。

Twitterで踊ったり音ゲーしたりしてるあの名前がよくわからない人が書いてるらしいよ。

動的にメソッドを追加して動的に呼び出す

動的型付けの言語だと、動的にメソッドを追加するとかいうのができます。

Ruby

Module#define_methodで定義できます。

define_method("foo") {
   puts "fooo!"
}

動的に呼び出すときはObject#send(メソッド名, 引数)呼び出せますが、privateなメンバーやメソッドであろうが容赦なく呼び出せるので要注意*1

JavaScript

プロトタイプベースの言語なので息を吸うようにできます。でないと困りますよね。

var obj = {};
obj.foo = function() { console.log("foooo!"); };

JavaScriptでプロパティやメソッドを動的に呼び出すときはこうします。

document["getElementById"]

騙されたと思ってF12を押してコンソールを開き、おもむろに打ち込んでみましょう。

PHP

PHP5.3からできるようになりました。5.4だとトレイトを使うと良さげですが。

class Foo {
    protected $methods = [];

    public function __set($name, $value) {
        if (is_callable($value)) {
            $this->methods[$name] = $value->bindTo($this);
        }
    }

    public function __call($name, $args) {
        if (is_callable($this->methods[$name])) {
            return call_user_func_array($this->methods[$name], $args);
        }
    }
}

$foo = new Foo;
$foo->bar = function($baz) {
    $this->baz = $baz;
};
$foo->bar('Hello');
echo $foo->baz . PHP_EOL; //Hello

呼び出すメソッドを変えるには次のようにするらしいです。

function foo1() { }
function foo2() { }
$c = "foo";
$c1 = $c."1";
$c2 = $c."2";
$c1(); //call foo1
$c2(); //call foo2

これはもっと早く知っておきたかった…

*1:privateメソッドのテストをするときなんかは逆に好都合かもしれませんね。