我已经阅读了几个关于PHP中抽象类的线程,但没有一个答案似乎解决了我的问题:为什么抽象类中的方法需要与子类具有相同的签名(相同的参数)不可能知道那些抽象方法的子类实现可能需要什么?抽象类的经典示例类似于GeometricShape()类,其中两个子类可能是类Rectangle extends GeometricShape()和类Circle扩展GeometricShape()。一个的getArea()方法需要长度和宽度作为参数,另一个需要半径。这应该如何在PHP中运行?
答案 0 :(得分:2)
length
,width
和radius
不应该是方法的参数,它们应该是类中的属性。想要获取对象的区域时,只需调用:
$area = $shape->getArea();
Rectangle
方法将返回length*width
,Circle
方法将返回pi*radius*radius
。
签名必须相同,因为此代码不知道它是在Circle
还是Rectangle
上运行,它需要处理所有GeometricShape
等价的对象。
答案 1 :(得分:1)
这是一个很好而有趣的问题。在像GeometricShape()这样的情况下,GetArea将没有参数。一个更好的例子是一个名为FillColor的抽象方法,它将颜色作为参数,如下所示:
abstract class GeometricShape
{
abstract function GetArea();
abstract function FillColor($color);
}
class Square extends GeometricShape
{
function GetArea()
{
echo "Square - get area\r\n";
}
function FillColor($color)
{
echo "Square - Filling color $color\r\n";
}
}
class Circle extends GeometricShape
{
function GetArea()
{
echo "Circle - get area\r\n";
}
function FillColor($color)
{
echo "Circle - Filling color $color\r\n";
}
}
$square = new Square();
$square->FillColor('green');
$circle = new Circle();
$circle->FillColor('red');
抽象类是为孩子们可以覆盖的孩子提供共同的个性。抽象类可以提供脚手架/基本属性,孩子们也可以按原样使用。
如果抽象方法应该提供更宽松的签名,则可以向其发送数组。这样,circle可以使用包含radius的数组覆盖方法,而rectangle可以发送长度和宽度的数组。方法体将使用该数组来确定已接收的内容以及如何处理它。
答案 2 :(得分:0)
我认为你正在混合各种概念
当您的类必须为类及其子类提供概念性限制时,抽象就会发挥作用。例如,从现实世界中举例,Tree
是概念性的东西,直到它物化为物质,例如Apple Tree
。如果你是博物学家,你想保持自然的东西是自然的(不喜欢遗传修饰!)并确保Apple Tree
确实产生苹果而不是芒果并且确实有roots
。现在重点关注roots
,fruit
w.r.t Tree
这两个词
和w.r.t Apple Tree
以及任何其他Xyz Tree
。当我们讨论这些关于Tree
时,它们是非常开放的结束接口,每个树应该具有或必须被称为Tree
(除非或直到它的GM一个)。 roots
中的Tree
接口是抽象接口bcz子类,即Apple Tree
知道如何从地面吸取矿物质来制作apple fruit
。因此,每个工厂都采用不同的方法来实现roots
接口。
在你的示例中,getArea()方法或多或少是方法覆盖的一个例子,其中一个孩子决定忽略/压制其继承行为/属性的某些部分。
我希望这个自然的例子不是那么复杂的