Mix-In

http://d.hatena.ne.jp/bobchin/20050914
前に、PHPのAggregate関数を使ってMix-Inみたいなことと書いたけど


http://www.programmers-paradise.com/tdiary/?date=20050915#p04
本来は禁じ手かもしれないが、わかっててやれば有効かもしれませんね・・・

作り方は

  • モジュールとして呼ばれる側(Foo)は、インスタンスメソッドとして定義する
  • モジュールを利用する側(Bar)は、モジュールをスタティックメソッドとしてコールする

ってかんじかな。


問題は

  • Fooがインスタンスかして利用できてしまう(コンストラクタで対応すればいいか・・・)
  • Barは必ずインスタンスで利用して欲しい
  • プロパティを使用する場合は、FooとBarでプロパティ名を合わせておく必要がある。

ってとこでしょうか?

こんなのはどう?


Mixin.php(Mixinモジュールで制限を加えるクラス)

<?php

class Mixin {
    function Mixin()
    {
        die("Mixinするモジュールはインスタンス化できません");
    }
    
    function check($vars = array())
    {
        isset($this) 
            or die("Mixinモジュールを使用するにはインスタンス化する必要があります");
        !is_a($this, __CLASS__) or die("Mixinモジュールは継承できません");
        
        Mixin::check_vars($vars);
    }
    
    function check_vars($vars)
    {
        $vars = (array)$vars;
        $real_vars = get_object_vars($this);
        foreach ($vars as $var) {
            isset($real_vars[$var]) 
                or die(get_class($this)."にプロパティ'{$var}'が存在しません");
        }
    }
}

?>


SampleModule.php(Mixinモジュール)

<?php
require_once 'Mixin.php';

class SampleModule extends Mixin {

    function println()
    {
        Mixin::check("s");
        print $this->s."\n";
    }

    function println2($var = "s")
    {
        Mixin::check($var);
        print $this->$var."\n";
    }
}

?>


Sample.php(ユーザクラス)

<?php
require_once 'SampleModule.php';

class Foo {
    var $s;
    var $s2;
    
    function setS($s)
    {
        $this->s = $s;
    }
    
    function println()
    {
        SampleModule::println();
    }

    function println2()
    {
        SampleModule::println2("s2");
    }
}

$foo = new Foo();
$foo->setS("ほげ!");
$foo->println();
//$foo->println2();
$foo->s2 = "uni";
$foo->println2();

?>