プログラムを共食いさせる

Blog Single

本日の雑学 「ウミウシの中には他のウミウシを食べる種類がいる」

どうも、元「魚のお姉さん」です!
大学時代、好きでウミウシを調べてプレゼンを行ったことがありまして。
冒頭に書いたように、ウミウシには他のウミウシを食べる種類がいるんです。
いわば共食いってことです。
それをふと思い出しておりまして、唐突に疑問が…

「プログラムが他のプログラムを共食いしたらどうなるんだろう…」
(始まりました、毎度お馴染みの脳内妄想です←)

というわけで

プログラムを共食いさせてみましょう

(今回も茶番にお付き合いください)

前提

知らない方はいないとは思いますが、改めて共食いとは以下の通りです。

動物においてある個体が同種の他個体を食べる事である。この現象に準えて、同業者同士で利益を得ようとして共倒れすることも共食いと呼ばれる。なお、ヒトがヒトを食う共食いに関してはカニバリズムを参照。英語では同業者同士で利益を得ようとして争うことをdog eat dogと言う。
Wikipediaより引用

基本条件

そもそもプログラムで共食いってどういうことなんだ、と思われるかもしれませんが、

共食い => 同種を飲み込んでしまう => 相手を上書きしてなかったことにしてしまう

つまりoverride!(無理やりすぎる
というわけで今回の基本条件として、以下のように設定してみました。

  • 言語はJavaScript
  • 食べられた側の情報をすべてoverrideすること

JavaScriptを共食いさせる

JavaScriptのoverrideは非常に簡単です。
他の言語では同じメソッド名があるとエラーになったりしますが、
単純にメソッドのoverrideをする場合は以下のように表現できます。

function getTest()
{
    return 'test';
}

function getTest()
{
    return 'test override';
}

console.log(getTest()); // => test override

今回ただこれだけでは面白くないので、
基本条件にもありますようにどんな名前のメソッドやプロパティが来てもoverrideするという処理を書いていきましょう。
それではまず、食べられてしまうオブジェクトを用意します。

// ウミウシA
var SeaSlugA = {
    name: "Sea Slug A",
    state: "Is Alive",
    getName: function() { return this.name; },
    getState: function() { return this.state; },
    setName: function(name) { this.name = name; }
};

中身は適当なのですが←
ひとまず簡単なプロパティとメソッドを設定しました。
続いてこのオブジェクトを食べる側のオブジェクトを作成します。

// ウミウシB
var SeaSlugB = {
    eat: function (otherSlug) {
        var otherSlugProperties = Object.getOwnPropertyNames(otherSlug);
        otherSlugProperties.forEach((prop) => {
            if (typeof otherSlug[prop] === 'function') {
                this[prop] = function() {
                    var func = otherSlug[prop].apply(otherSlug, arguments);
                    if (func === undefined) return func;
                    return func + " is override";
                };
            } else {
                this[prop] = otherSlug[prop] + " is override";
            }
        });
    }
};

定義上は共食いするeatメソッドのみを設定します。
このメソッドで食べたウミウシのすべての要素をoverrideして吸収させています。
引数のあるメソッドにも対応できるようにFunction.prototype.apply()で相手のメソッドを呼び出すようにしました。

早速、この共食いを実行しましょう。
簡単な処理なのでターミナルのJSCコマンドで実行します。
ちなみにJSCコマンドの設定は以下のシェルコマンドでできます。

cd /usr/local/bin
ln -s /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc ./

出力用のコードを書き足して、いざ実行!

// 共食いさせる
SeaSlugB.eat(SeaSlugA);

// 各プロパティがoverrideされたか確認
print("name: " + SeaSlugB.name);
print("getName: " + SeaSlugB.getName());
print("state: " + SeaSlugB.state);
print("getState: " + SeaSlugB.getState());
SeaSlugB.setName('Sea Slug B');
print("getName: " + SeaSlugB.getName());

最後に

メソッド名がわからない相手であろうと、なんでもかんでもoverrideさせる。
という意味ではまとまって書けたかなというイメージではありますが、
ちょっと共食いという概念がずれてしまいましたかね。。
もう少し同種感を強めたかったのですがまだまだ詰めが甘かったですね←精進します
今回も茶番にお付き合いいただき、ありがとうございました!

参考

Posted by Mao Miyaji
千葉にある夢の国を愛して止まない、元「魚のお姉さん」のエンジニア。PHP, TypeScriptメインで、暇さえあれば色々な言語を一かじり。

Other Posts: