0

手続き型コードからクラス アーキテクチャに移行するプロジェクトに取り組んでいますが、対処方法がわからない問題に遭遇しました。次のコードを参照してください。

// StackOverflow example code
# in file classes/parent_class.php
class Parent_class {
  protected $aggregator_array = array();
  const TARGET_DATA_LEVEL = 31; // Bit-mask for selecting appropriate aggregation level

  public function __construct()
  {
    $this->child_class_1 = new child_class_1();
    $this->child_class_2 = new child_class_2();
  }

  protected function aggregate_data($data_level, $message, $file, $function, $line)
  {
    $add2array = $data_level & self::TARGET_DATA_LEVEL;
    if ($add2array > 0)
    {
      // code to create the array's index, based on current time and other factors
      $this->aggregator_array[$index] = $message;
    }
  }
}

# in file classes/child_class_1.php
class child_class_1 extends Parent_class {
  private function do_something()
  {
    // some code here
    $data_level = 1; // simulate an error of some kind
    $message = 'Foo!';
    $this->aggregate_data($data_level, $message, __FILE__, __FUNCTION__, __LINE__);
  }
}

# in file classes/child_class_1.php
class child_class_2 extends Parent_class {
  private function do_something_else()
  {
    // some code here
    $data_level = 2; // simulate nav message
    $message = 'hello world!';
    $this->aggregate_data($data_level, $message, __FILE__, __FUNCTION__, __LINE__);
  }
}

ご覧のとおり、データ集約メソッドを含む親クラスと、スクリプトの実行の最後に後で取得するためにメッセージを保存するために同じメソッドにアクセスしようとする複数の子クラスがあります。これは、目的 (集約されたメッセージを中央の配列に収集すること) が実現されていないことを除いて、すべて問題ありません。aggregate_data への呼び出しはすべて正常に機能していますが、子クラスから呼び出しを行うと、その子自身の aggregator_array にデータが格納されるため、最適ではありません。確かに、array_merge() を実行して子エントリを親配列に挿入することはできますが、子クラスが 2 つ以上ある場合 (6 つ以上あると予想される場合)、コーディングについて話していることになります。悪夢。静的プロパティを使用してみましたが、明らかにうまくいきません。

私の質問は、同じ名前の子プロパティを作成せずに、子クラスから親オブジェクトのプロパティを変更するにはどうすればよいですか?

現在、「関連のない」クラスを使用しても問題ありませんが (たとえば、現在の子クラスから「extends parent_class」を削除するなど)、問題は関連のないクラスのプロパティとメソッドにアクセスする方法に移ります。可能であれば、どうすればよいかという最も漠然とした手がかり。

4

1 に答える 1

1

child_class_* オブジェクトは本当に別の種類の Parent_class ですか? それとも、いくつかのものを集約するために、たまたま Parent_class とやり取りしているだけですか? メソッド名 do_something および do_something_else に基づいて、それらは実際にはその種のロジックに対して責任を負いません。たとえば、aggregate_data() の動作をポリモーフィックに変更したい場合など、特定の種類の Parent_class の特定の動作をオーバーライド/定義していない限り、おそらく Parent_class を拡張する必要はありません。

つまり、「無関係な」クラスのプロパティにアクセスする方法の 1 つは、Parent_class のインスタンスを do_* 関数に渡すことです。

// in your main script
$aggregator = new Parent_class();
$thing1->do_something( $aggregator );
$thing2->do_something_else( $aggregator );

// in child_class_1, which you should rename ;-)
private function do_something( $aggregator )
{
    ...
    $aggregator->aggregate_data( $data_level, $message, __FILE__, __FUNCTION__, __LINE__ );
}

// in child_class_2, ditto
private function do_something_else( $aggregator )
{
    ...
    $aggregator->aggregate_data( $data_level, $message, __FILE__, __FUNCTION__, __LINE__ );
}

または、Parent_class のインスタンスを 2 つの「子」クラスのコンストラクターに渡すこともできます。これにより、do_* メソッドのメソッド シグネチャが乱雑になりにくくなります。次に、次のようなことができます。

// main script
$aggregator = new Parent_class();
$thing1 = new child_class_1( $aggregator );
$thing2 = new child_class_2( $aggregator );

// within each of the do_* methods:
$this->$aggregator->aggregate_data( $data_level, $message, __FILE__, __FUNCTION__, __LINE__ );

このアプローチでは、「子」クラスに $this->aggregator を設定するコンストラクターも必ず追加してください。

コードの後半で、呼び出しなどによって「中央配列」にアクセスできます$aggregator->GetAggregatorArray

また、 を初期化$indexしていませんが、とにかくその変数は必要ありません ($aggregator_arrayが数値配列であると仮定します)。あなたはただ行うことができます:

$this->aggregator_array[] = $message;
于 2013-06-28T18:54:20.527 に答える