【问题标题】:Why would you extend a class rather than just adding a new method to the original class?为什么要扩展一个类,而不是仅仅向原始类添加一个新方法?
【发布时间】:2023-03-18 20:48:01
【问题描述】:

当谈到 OOP 课程时,我终于有了我的“啊哈”时刻。我一直在努力思考这个想法。现在我开始明白了,我想知道扩展一个类的目的是什么。只是在类中添加另一个方法不是更简单,还是我错过了重点?

【问题讨论】:

  • 目的是避免代码重复。并访问上述类的所有方法。

标签: php oop methods extend


【解决方案1】:

如果您想为类添加功能,请添加方法。但是,在某些情况下,您想要添加功能,但无法在基类中执行此操作。

最好的例子是展示。将方法 Radius 添加到类时,仅当类是 Circle 时才有意义,Rect 没有半径。在基类中添加方法Radius 也没有任何意义,因为Rect 类也会获得方法Radius

例子:

abstract class Shape
{
  abstract public function Draw();
}

class Rect extends Shape
{
  public function Draw()
  {
  }
}

class Circle extends Shape
{
  public function Draw()
  {
  }

  public function Radius()
  {
  }
}

【讨论】:

  • 我知道你要去哪里......但是向扩展类添加绘图方法不会破坏在形状类中绘制的目的吗?从而使扩展类的全部原因(DRY 编码)变得毫无意义?
  • shape类中的draw方法应该是抽象的,没有办法画出Shape。我调整了示例。
  • 好的,现在看来我还有更多的阅读和理解要做。感谢您为我指明正确的方向。
【解决方案2】:

有时原始类是您无法更改的库的一部分。

有时您想以多种不同的方式扩展超类。

例如(java语法代替PHP但是思路是一样的):

class Shape {
  abstract double getArea();
}

class Square extends Shape {
  double getArea() {
    return size * size;
  }
}

class Circle extends Shape {
  double getArea() {
    return radius * radius * Math.PI;
  }
}

对于接受 Shape 类型参数的方法,您可以传入 Squares 和 Circles。该方法不需要知道它得到哪一个,但仍然可以调用 getArea()。如果您只是将方法添加到 Shape 类,这将不起作用。

【讨论】:

  • 因为正方形有 getCircumference() 方法没有意义。为什么现在不正确?在我看来是对的。您在方法中的计算是针对面积的。另外,自从我编辑它后,你已经获得了 3 次赞成票(当时是 -1)。
  • 为什么你认为它没有意义?一个正方形的周长是它的边的总和。该区域是其两侧的产物。计算的是周长,而不是面积。
  • 好吧,我错了,但正方形不能有circumference,可能是周长,但不是周长。
  • 我想 Perimeter 会是一个更好的词。不过,这些公式绝对不适用于面积。
  • 你会习惯的,看这个解释stackoverflow.com/faq#editing。在我们之间,您最终得到了 3 次投票的好答案,而不是您最初投反对票的答案,可能是因为反对票的人被带圆周的正方形弄糊涂了。
【解决方案3】:

这将是一个简化,但给你一个现实生活中的例子:

假设您要创建一个内容管理系统,即根据用户输入在您的网站上显示不同页面的脚本。

您可能希望每个页面(我们称它们为模块)都具有特定的功能,例如在该页面/模块上时允许执行的命令。然后,这些不同的命令可以是每个模块类中的不同方法。

但是,如果您允许登录命令,无论用户当前在您网站的哪个位置,会怎样?即,这将是所有模块之间共享的命令。

您的解决方案可以通过拥有一个父模块类来解决,登录方法将驻留在其中,并且可由所有模块执行。

// Your parent class
abstract class ParentModule 
{
   protected function login()
   {
      // Login stuff
   }
}

// One of your modules
final class ArticleModule extends ParentModule
{
    public function submit_article()
    {
        // An example function
    }
}

// Another one of your modules that the user could still login from
final class AnotherModule extends ParentModule
{
    public function another_command()
    {
        // Magic
    }
}

您的控制器可能如下所示。

$module = new ArticleModule();
$module->login();
$module->submit_article();

最后,当你开始研究接口时——我花了很长时间才明白这些——你会再次看到抽象类的好处。确实,如果你完全掌握了抽象类的概念,你会更容易理解接口。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多