我是OOP的新手,并且使用接口了解多态性。有一个流行的多形态例子是根据形状计算面积。
代码:
<?php
interface Shape {
public function calcArea();
}
class Circle implements Shape {
private $radius;
public function __construct($radius) {
$this -> radius = $radius;
}
public function calcArea() {
return $this -> radius * $this -> radius * pi();
}
}
class Rectangle implements Shape {
private $width;
private $height;
public function __construct($width, $height) {
$this -> width = $width;
$this -> height = $height;
}
public function calcArea() {
return $this -> width * $this -> height;
}
}
$circ = new Circle(3);
$rect = new Rectangle(3,4);
echo $circ -> calcArea();
echo '<br />';
echo $rect -> calcArea();
?>
这是完全没有使用界面的相同代码:
<?php
class Circle {
private $radius;
public function __construct($radius) {
$this -> radius = $radius;
}
public function calcArea() {
return $this -> radius * $this -> radius * pi();
}
}
class Rectangle {
private $width;
private $height;
public function __construct($width, $height) {
$this -> width = $width;
$this -> height = $height;
}
public function calcArea() {
return $this -> width * $this -> height;
}
}
$circ = new Circle(3);
$rect = new Rectangle(3,4);
echo $circ -> calcArea();
echo '<br />';
echo $rect -> calcArea();
?>
两者都按预期工作,但界面实际上没用!到目前为止,OOP似乎只是为了增加更多不必要的复杂性。我们使用类和通用接口,而不是切换或条件。我发现实际上更容易使用IF或切换条件(只要你不要重复相同的代码)而不是在一个单独的类中的每一个。
OOP的唯一好处似乎是在设计API时。因此,API的最终用户实际上可以直接访问所需的方法,而无需调用大量不需要的代码。
但是,从开发人员方面来看,您对某个类应用的任何修改实际上也可能需要对代码的其他部分进行修改。此外,开发人员无论如何都必须查看代码的其他部分才能理解它是如何工作的。此外,HTML中的内联PHP将存在,因此对某个方法的任何修改都可能需要更改所声明对象的实例。
我错过了什么吗?
答案 0 :(得分:1)
我认为这个问题更适合Programmers SE。
无论如何:你最小的例子是 - 最小的。是的,在这种情况下,使用该接口将被视为 overkill ,但有许多用例,其中实现/指定接口确实有意义。
如果您正在开发开源,您可能需要指定一个界面,即使您当时是唯一的开发人员,只是为了确保未来的贡献者能够轻松访问您的代码并且可以为您的项目提供自己的扩展/添加。
但即使在最小的例子中,也有一些用例:想象一下应用程序,其中应用程序的某些部分通常处理Shape
个对象。想象一下,要处理的实际形状并不重要。
使用该接口时,您必须为所有派生类实现该方法。这允许可扩展性和可维护性。
另请参阅同一主题的this SO post。
答案 1 :(得分:0)
这是一个很好的问题,我看到人们一遍又一遍地问它。所以我会尝试为你简化它,(接口部分到底)。
首先,你不一定非常需要在任何地方使用OOP,大多数wordpress核心代码是用程序性的php编写的(不确定当前版本),并且它不是坏事。大多数时候它确实为新程序员简化了事情,这就是使用OOP的全部意义,即在抽象上添加抽象,所以当程序员正在处理特定的功能时,他不必担心其他方面。因此,例如,如果我想存储注册表单中的图像,我将有2个类。一个用户,一个用于图像。所以这就是它的样子。
/*********** User Class ***********/
Class User
{
public function storeUser($request, Image $image)
{
// Fetch Image from the form request and pass it to the
$image = $request->input('image');
$image->uploadImage($image, $imagePath);
// Now upload other user attributes
}
}
/ ********* Image Class **********/
Class Image
{
public function uploadImage($image, $imagePath){
// Code to UploadImage
}
}
我通常有一个名为users的类和一个名为storeUser的方法,我将把用户添加到数据库中。现在我还有另一个名为Image的类,其方法名为uploadImage。
你可以用一个也很好的功能完成同样的事情,但是如果你想要另一个功能,可以说当用户更新他的个人资料时,删除旧图像并上传一个新图像。为此你必须包含另一个函数,它将包含uploadimage的所有代码和一些其他代码来删除前一个图像。
但现在你正在重复自己,并避免干燥原则(不要重复自己)。但是假设你有另一个deleteUserImage函数,它会删除图像,然后调用上传函数。
因此,如果你正在考虑这样做,那么你实际上是在下意识地使用OOP,但是以一种非常混乱的方式,因为一个类只是函数和变量的集合。但是你缺少许多其他功能,比如示波器,静态,其他一些很酷的东西以及我最喜欢的$ this:)
您添加的抽象数量取决于您的截止日期,未来的可扩展性等。您不必绝对对抽象感到疯狂,但一个简单的经验法则是您拥有的抽象越多,您的代码就越易于管理和灵活。 。
让我们说你已经在php和mysql中创建了你的应用并推出了它,但是应用程序变得非常受欢迎,然后你预期。突然你有数百万用户,但是你的mysql服务器在某种程度上不支持这么多的用户,你想转移到另一个数据库,如postgres或cassandra,但你的所有mysql查询都与PHP代码混淆,没有无痛的方法来实现这一点,但从头开始创建一切。这是许多大型组织经历过的常见问题,包括Twitter和Facebook。但是如果您使用抽象创建了应用程序,所有查询都在一个类中,那么您的控制器将进入另一个类。您只需在几个文件中修改驱动程序和查询,就可以开始使用另一个数据库。
现在让我们回到关于界面的原始问题。您可能认为界面只是浪费时间,因为它只是您要在课堂上实现的所有方法的列表, 对?至少在我开始OOP时,它似乎在我看来。但事实证明我是愚蠢的,因为当时我并不知道 SOLID Principles 。
SOLID实际上是为编程编写的5个最佳原则的缩写,它们相互支持得非常好。 SOLID中的“O”代表“开放和封闭原则”,它的含义是该方法对于更改是封闭的,但是为扩展打开。简单来说,这意味着一旦你有一个基本的工作应用程序,你永远不应该修改你的界面中现有的方法参数,因为如果其他文件也使用该类,它将破坏它们。你通过接口增加限制的方式。那么如何在不修改方法的情况下添加新功能呢?好吧,你不要直接修改方法,你可以扩展它。