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() 来将子条目插入到父数组中,但是如果我有多个子类(并且我希望有六个或更多),我们正在谈论编码恶梦。我试过使用静态属性,但这显然行不通,因为我

所以我的问题是,如何在不创建同名子属性的情况下从子类更改父对象的属性?

现在我非常乐意使用“非相关”类(例如,从当前子类中删除“扩展 parent_class”),但问题随后转移到如何访问不相关类的属性和方法,而我没有如果可能的话,如何做的最模糊的线索。

4

1 回答 1

1

child_class_* 对象真的与 Parent_class 不同吗?或者他们只是碰巧与 Parent_class 交互以聚合一些东西?基于方法名称 do_something 和 do_something_else,他们真的不负责那种逻辑。除非您覆盖/定义特定类型 Parent_class 的某种行为,例如,如果您希望 aggregate_data() 的行为多态地改变,您可能不需要扩展 Parent_class。

也就是说,您可以访问“不相关”类的属性的一种方法是将 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 的实例传递给您的两个“子”类的构造函数。这样可以使您的 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 回答