2009-08-19 20 views
0

クラスのメソッドをカプセル化することはできますが、それを消費するクラス内に公開することができるのだろうかと思います。例えばカプセル化と継承のメソッド

class Consumer{ 
     public function __construct($obj){ 
      $this->obj = $obj; 
      } 

     public function doCommand(){ 
      $this->obj->command(); 
      } 
     } 

    class Consumed{ 
     //I would make the constructor private, but to save space... 
     public function __construct(){} 
     private function command(){ 
      echo "Executing command in the context of the Consumer"; 
      } 
     } 

    $consumer = new Consumer(new Consumed); 
    $consumer->doCommand(); 

    //just to reiterate, I know this throws an error 

は最終的に、私が直接、単一の制御クラスのコンテキスト外で参照することができない部品を作ることができるようにしたい(JFTR、私はこのコードが間違っている知っています)。

+0

あなたはC++の友達クラスのようなものを意味していますか? http://en.wikipedia.org/wiki/Friend_class – VolkerK

+0

あなたはそれを双方向にすることはできません。プライベートメソッドの中に機能を隠している場合は、外部から呼び出すことはできません。 パブリックメソッドを呼び出すと、プライベートメソッドが呼び出されます。パブリックメソッドを呼び出すと、すべてのユーザーがプライベートメソッドを呼び出すことができます。 –

+0

上記のコメントはもちろんPHPです:friendクラスは動作しますが、PHPにはそのような概念はありません。 –

答えて

0

ことができることを確認して、ちょうどそれらのメソッドprotectedを作る、ないprivateConsumerから延びるConsumed持っています。私はしかし、利点についてはよく分かりません。

+0

を使用して、メソッドへの直接アクセスを防ぎ、単一の入力ポイントを強制します。これはデザインの観点から悪いですか? – sunwukung

+0

かもしれません。つまり、「Consumed」クラスは基本的にはテストできません。パブリックインターフェイスを持たないクラスの目的は何でしょうか?たぶんそれはあなたが本当にそのクラスを必要としていない兆候かもしれません。アクセス制限は必ずしも良い設計を保証するものではありません。あなたが解決しようとしている**問題**は何ですか? –

+0

本当に - 私はちょうど被験者を勉強しています。私は自分自身のMVCをその一部として巻き起こしています(冗長ですが、知っていますが、私が学ぶのを助ける知的練習です)。私のプレゼンテーション層には、View Controllerが部分テンプレートをマスターに提供するために使用するオブジェクトのクラスがあり、そのオブジェクトが直接アクセスされないようにしたいと考えています。 戦略/コマンドパターンを見てから考えました - 私が見た例では、消費されたコンポーネントに直接アクセスすることができました。そして、単一のエントリポイントが原則のポイントとして認められたようでした。 – sunwukung

1

__calldebug_backtraceのようなものをエミュレートできます。

<?php 
class Consumer{ 
    public function __construct($obj){ 
    $this->obj = $obj; 
    } 

    public function doCommand(){ 
    $this->obj->command(); 
    } 
} 

class Consumed { 
    // classes that are aloowed to call private functions 
    private $friends = array('Consumer'); 

    public function __construct(){} 
    private function command() { 
    echo "Executing command in the context of the Consumer. \n"; 
    } 

    public function __call($name, $arguments) { 
    $dt = debug_backtrace(); 
    // [0] describes this method's frame 
    // [1] is the would-be frame of the method command() 
    // [2] is the frame of the direct caller. That's the interesting one. 
    if (isset($dt[2], $dt[2]['class']) && in_array($dt[2]['class'], $this->friends)) { 
     return call_user_func_array(array($this,$name), $arguments); 
    } 
    else { 
     die('!__call()'); 
    } 
    } 
} 

$c = new Consumed; 
$consumer = new Consumer($c); 
$consumer->doCommand(); 

echo 'and now without Consumer: '; 
$c->command(); 

プリント

Executing command in the context of the Consumer. 
and now without Consumer: !__call()