如何避免在 PHP 中重复实现的 getter 函数

How to avoid duplicating implemented getter function in PHP

虽然这个问题是关于解决这个问题的方法,但我对符合当前 PHP 最佳实践的良好干净的 OO 设计和解决方案特别感兴趣。在此先感谢您的关注。

我有以下界面:

<?php

interface Tool {

  /**
   * Return the unique name of the tool
   */
  public function getName();

}

在我的项目中实现此接口的大多数 classes 如下所示:

<?php

class Drill implements Tool {

    protected $toolName = 'drill';

    public function getName() {
        return $this->toolName;
    }

}

所以 问题 是我有几十个 classes 重复这个逻辑,复制 $toolName 属性 和 getName() 逻辑,打破“不要重复自己”的简单规则

我考虑过的一个解决方案如下:

<?php

abstract class BaseTool implements Tool {

    public function getName() {
        return $this->toolName;
    }

}

然后简单地使用工具 classes 扩展抽象 BaseTool class:

<?php

class Drill extends BaseTool {

    protected $toolName = 'drill';
}

然而,这现在意味着我无法强制实现 classes 来定义函数 getName(),如果它们扩展了 BaseTool class,这可能会导致不正确的实现。

我还认为通过使用 BaseTool class return $this->toolName,它正在对实现 classes 做出假设并破坏封装。

我已经使用了一个简单的例子来说明这个问题,但希望你能理解我要解决的问题,并且这个问题也可能与更复杂的情况有关。欣赏你的想法。

如果您使用的是 PHP 5.4.0+,请查看 traits

您可以创建一个只包含变量 $toolName

的 getter/setter 的 ToolInterfaceTrait

你的尝试看起来不错。没什么好说的了。

However this now means that I lose the ability to force implementing classes to define the function getName() if they extend the BaseTool class, which can lead to incorrect implementations.

你还是强迫他们,他们需要继承一个class来实现它们,或者自己实现。

如果所有应该实现 Tool 的 classes 都从 BaseTool 扩展是不可行的,请随意创建更多实现 [=] 的基础 classes 12=] 或直接实现它,如您所愿。

顺便说一句,如果您计划所有工具都应该扩展 BaseTool,那么接口根本就不是必需的,至少对于这个用例而言不是这样。接口用于并非所有需要实现它的 class 都是从相同的基础 class.

继承的情况

How to avoid duplicating implemented getter function in PHP

抽象 classes 通常用于对重复代码进行分组。你走在正确的道路上。至于你对选择的疑惑...

However this now means that I lose the ability to force implementing classes to define the function getName() if they extend the BaseTool class, which can lead to incorrect implementations.

通过扩展 BaseTool class,一个 class 继承 getName() (这就是在抽象中定义它的想法 class).我不确定为什么这会导致不正确的实现或者为什么你必须 "force implementing classes to define it." 他们通过扩展抽象 class.

自动获得它

I also think that by having the BaseTool class return $this->toolName, it is making assumptions about the implementing classes and breaks encapsulation.

如果在抽象 class 中定义 toolName 并在构造函数中设置它的值,可能会更清晰?

<?php

abstract class BaseTool implements Tool {

    protected $toolName;

    public function __construct($toolName)
    {
        $this->toolName = $toolName;
    }

    public function getName() {
        return $this->toolName;
    }

}

您在扩展class中定义一个构造函数来放置它的名字:

<?php

class Drill extends BaseTool {

    public function __construct()
    {
        parent::__construct("drill");
    }

}