3

Foo多数のパブリック メソッドとプライベート メソッドを持つクラスがあります。これらのメソッドの 1 つがかなり大きくなってきているので、その目的専用の別のクラスにフォークしたいと考えています。このようなもの:

<?php

class Foo
{
  //  ...

  public function doX( $a, $b )
  {
    $x = new FooXDoer;
    $x->foo = $this;
    return $x->run( $a, $b );
  }

  //  ...
}

class FooXDoer
{
  public $foo;

  public function run( $a, $b )
  {
    // ...
  }

  // ...
}

FooXDoerFooは、 を介して のパブリック メソッドとプロパティにアクセスできます$this->foo

を既に使用している残りのコードに公開せずに、 のプライベート メソッドとプロパティFooXDoerへのアクセスを許可するにはどうすればよいですか?FooFoo

FooPrivateプライベートメソッドをパブリックとして持つ別のクラスを作成し、FooラップしてからFooXDoer参照する必要がありますか? 何FooPrivateと呼ぶべきですか?

それとも私のアプローチは完全に間違っていますか?一般的に、この問題をどのように解決しますか?

4

2 に答える 2

4

PHP >= 5.4 を使用する場合、特性が問題を最もよく解決するように見えます。

そうでない場合、次の解決策を考えました。

class A {
    private static $allowedClasses = array('B');
    private $a = 1;

    public function __get($property) {
        $caller = debug_backtrace(false);
        if(!isset($caller[1]))
            throw new Exception('Bla bla');
        if(!in_array($caller[1]['class'], self::$allowedClasses))
            throw new Exception('Bla bla');
        return $this->$property;
    }

    public function testB() {
        $b = new B();
        $b->instA = $this;
        echo $b->getA();
    }

}

class B {
    public $instA;
    public function getA() {
        return $this->instA->a;
    }
}

class C {
    public function getA() {
        $instA = new A();
        return $instA->a;
    }
}

$a = new A();
$a->testB(); // Works ok;
$c = new C();
$c->getA(); // Throws exception here;

このコードは間違いなくベスト プラクティスではありません :) しかし、可能であるため、ここに記載します。

于 2012-07-25T08:26:14.483 に答える
2

PHP にはフレンド クラスの概念がありません。私が読んだ限りでは、PHP 設計者による悪い決定とは言えません...

私見、問題または質問が広すぎるため、一般的な戦略はありません。考慮すべき要素が多すぎます。

  • にはいくつのプライベート プロパティとメソッドFooが必要run()ですか?
  • 抽象化の観点から: はどれくらい密接にrun()巻き込まれていFooますか? 独立したクラスにいることは本当に「価値がある」のでしょうか?
  • FooXDoerの外で使うことはありFooますか?

解決策の 2 つのアイデア:

値ごとに、または配列またはオブジェクトを返すonを実装することにより、必要なデータを からfooに渡します。fooDoercompileRunData()Foo

public function doX( $a, $b )
{
 $x = new FooXDoer;
 $workEnvironment = $this->compileRunData();
 $x->setEnvironment( $workEnvironment );
 $x->foo = $this;
 return $x->run( $a, $b );
}

または継承、特に保護されたプロパティの概念を使用します。

abstract class FooAbstract
{
 protected $_basicVar1;
 protected function basicMethod1(/*...*/) {
  //...
 }
 // ...
}

abstract class FooRunner extends FooAbstract
{
 protected $_runVar1;

 protected function runMethod1(/*...*/) {
  //...
 }

 public function run($a, $b) {
  // ...
 }
}

public class Domain_Model_Foo extends FooRunner 
{

}

編集:ねえ、SOはすでに答えがあることを私に示しませんでした。ええ、特性についても考えましたが、今まで使用したことがないので、実際にコメントすることはできません

于 2012-07-25T08:35:14.707 に答える