面向对象编程抽象类何时应实现抽象方法

5

我正在尝试学习PHP中的面向对象编程,目前我已经学到了抽象类。

我有一些问题不太理解,在抽象类中何时应该实现抽象方法,何时不应该。

例如,以下是一段代码:

<?php

abstract class concept_car {
    /**
     * Properties can not be declared as abstract natively:
     * https://dev59.com/42sz5IYBdhLWcg3w0rVC
     */
    protected $weelNum  = NULL;
    protected $doorsNum = NULL;
    protected $color    = NULL;
    protected $carType  = NULL;
    // the inheritance class must define this methods
    abstract public function setWeelNum($weelNum);

    abstract public function setDoorsNum($doorsNum);

    abstract public function setCarType($carType);
}

我不确定是否应该将这三个方法声明为抽象方法,还是要删除abstract并在类中实现这些方法,因为属性和方法在同一个类中。
在代码的实际形式中,我认为我必须在这里将这些方法声明为抽象方法,并在继承类中实现它们,在子类中实现,但我不知道这是否是正确的方式。
P.S:我是初学者,正在尝试理解事物的运作,我还没有涉及到设计模式,请用概念向我解释,以便我知道正确的操作方式。

2
实际上,它们只是setters。我认为你现在应该实现它们。 - crush
我建议您将类和对象视为其现实生活对应物的比喻,针对真实事物提出相同的问题并尝试回答,您很可能会得出良好的设计。此外,请考虑设计决策将如何影响您未来的代码库,例如在这里,如果您不实现那些set*()方法,则以后必须在每个汽车类中实现它们。 - Paul
还有,请不要套用设计模式的刻板印象。好的代码自然会产生模式,你只需要先编写面向对象的代码而不必想着使用模式(至少现在是这样)。那些模式只不过是一组常见类的名称,大家都知道它们的行为方式罢了。 - Paul
@Paul 谢谢您的解释,我会尽力保持正确的方向。 - Starlays
2个回答

7

你需要问自己一个简单的问题:

所有继承这个类的类都做同样的事情吗?

对于这个例子,答案是肯定的,它们都会做相同的事情。

public function setWeelNum($weelNum) {
  $this->weelNum = $weelNum;
}

因此,不要在每个类中复制/粘贴该代码,这没有意义。

什么时候应该声明抽象方法?

当该类的所有子类必须以不同的方式实现此方法时。

例如,在Animal类中,您将拥有一个public abstract function move();,因为所有动物都会移动,但您不知道具体是如何移动的。


3
我认为这是一个接口(interface)的例子,而不是抽象类(abstract class),因为该班级的所有孩子都必须按不同的方式实现这个方法。 - crush
@crush 我完全同意你的观点。 - zessx
我也同意,没有人说抽象类不能实现该接口。 - SteeveDroz
1
@Starlays 简而言之:在没有公共祖先的类中使用接口。如果有公共祖先,则使用抽象类(这个抽象类) - Voitcus
1
当您仅描述接口时,应使用接口...这就是为什么它被称为接口。抽象类确实应该有一些共同的成员,就像@Starlays上面的示例一样。 - crush
显示剩余2条评论

4
通常情况下,应该在最后的公共祖先类中实现所有方法。因此,如果您希望子类表现出相同的行为方式,请立即实现它们。如果它们需要被实现,但由不同的类以许多方式实现,请将它们保留为抽象的。
事实上,抽象类只是为了要求如果有人从这个公共类中继承某些东西,他将提供这些方法(抽象类类似于接口)。
如果您实现了所有方法,则无需使用抽象类。

它们是该基类属性的“默认”设置器。我认为它们应该在该类中实现。如果每个基类都要以不同的方式实现它们,那么这应该是一个接口,而不是抽象类。 - crush
@crush 是的,我错过了那个,这样很难想象他们还能做些什么(通知观察者?)。我认为Oltarus的回答解释得更好。 - Voitcus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接