名词解释: oop_OOP中的魔术方法:权威指南(PHP)

名词解释: oop

如果您可以定义将来可能发生的某些情况或事件,当它们发生时,将自动触发您的代码来执行您想要的事情,那将不是很好吗?

这些是魔术方法的力量,

继续阅读以发现这些面向对象技术之外的秘密

跟随系列...

这篇博客文章是“ 面向对象编程的完整指南:从过程编程到PHP的 OOP专家”的第五部分。

如果您还没有阅读其他部分

您可以通过以下链接查看其他博客文章
面向对象程序设计导论
PHP中的继承和接口 ,
更多接口和多态性
可见性和静态关键字 ,
构造函数和魔术方法
尚未发布的抽象类和额外位,请订阅以得到通知

表中的内容

  • 什么是魔术方法?
  • 构造函数
  • 依赖注入
  • 可选参数
  • 类型提示
  • __destruct()方法
  • __call()和__callStatic()方法
  • getter和setter方法
  • toString方法
  • __sleep()和__wakeup()夫妇
  • __invoke()方法
  • __set_state()和var_export
  • 使用__debuginfo()进行调试

构造函数和魔术方法

什么是魔术方法?

现在是时候在本文上撒些星尘了。

我相信您在您的Web开发职业中已经遇到了一些奇怪的符号。

在这种情况下

我说的是在原始名称前加上两个奇怪的下划线(__)的方法。

这些被称为“魔术方法”,它们在面向对象的编程中使用,使您可以在使用特定对象时响应指定的情况。

简而言之,这些方法指定了在这些情况下的React方式。

构造函数

构造函数可能是PHP中最常用的魔术方法。

有几种设计模式可以利用此方法的功能,

它由命令定义:

函数__construct()

如果类具有此方法,则每次实例化新对象时都将调用该方法。

使用构造函数方法时,类的行为会根据类是否为子类而改变。

如果子类未指定构造函数,则对象的行为将从父类继承,就像您之前已经看到的其他方法一样。

您还可以专门覆盖行为或加载父行为并根据需要进行编辑。

现在,

当建造一个新的公寓楼时会发生什么?

建筑物的经理需要赚一些钱来支付费用。

为此,他开始寻找租户。

您可以在代码中执行以下操作

 class Building 
{
     function __construct() 
{
         print "The building is complete. \n"; 
}
}
 class Apartment extends Building 
{
     function __construct() 
{
parent::__construct();
         print "Now looking for tenants."; 
}
}
 $mainStreet1025 = new Apartment(); 
// the code will output:
“The building is complete.
 Now looking for tenants.” 

在实例化位于$ mainStreet1025的公寓时,程序将自动输出定义的行。

依赖注入

你们当中的某些专家可能想知道为什么我还没有解释什么是依赖注入,而另一些人肯定一直在奇怪地看着方法名称上附加的括号,询问它们的含义以及它们在那里的原因。

好,

那一刻到了。

Laracasts的策展人Jeffrey Way有一个理论,我想与您分享:

名词解释: oop_OOP中的魔术方法:权威指南(PHP)_第1张图片

你知道宇宙中最小的恒星如何被称为吗?

白矮星!

您能告诉我显示出如此强大的引力效应的时空区域的名称是什么,哪怕是粒子和电磁辐射(例如光)都无法从其内部逸出?

无非就是黑洞。

您认为,他认为,我同意天文学家是世界上最聪明的人之一,他知道,我知道,他们知道。

对于我们开发人员而言,情况有所不同。

我们必须感到聪明,我们必须一直展示所有的神经元。

大部分时间都翻译成依赖注入之类的东西。

依赖注入无非就是一种非常简单的技术,它以一种非常奇特的方式命名,以使其看起来非常难以理解,并使使用它的人看起来是房间中最聪明的人。

那是什么

依赖注入是一种提供给定代码段所需的对象的方法。

所需的对象称为依赖项。

基本上,不是让对象创建依赖关系,而是将所需的依赖关系从外部传递给对象,

这允许开发人员使用变量参数而不是固定参数来创建对象。

例子来了...

 $windowsCount = 10; 
 $wallsColor = “red”; 
 $roomsCount = 3; 
 $myBuilding = new Building($windowsCount, $wallsColor, $roomsCount); 
 $windowsCount = 14; 
 $wallsColor = “green”; 
 $roomsCount = 6; 
 $yourBuilding = new Building($windowsCount, $wallsColor, $roomsCount); 

这边有

您刚刚发现了括号内的内容。

如您所见,利用此技术将非常有用,它允许您的代码创建不同的对象,并且它们中的任何一个都具有不同的特性。

例如, $ myBuilding具有红色墙壁和4个房间,而$ yourBuilding具有6个房间和绿色的墙壁。

而已!

正如我告诉您的,这是5美分概念的25美元术语。

即使这是一个简单的概念,我还是决定等到现在,因为既然您知道什么是结构,就可以轻松理解本文中的以下示例。

实例化新对象时,会自动调用__construct方法。

现在,您可以执行以下操作:

 class Building 
{
     function __construct($windowsCount, $wallsColor, $roomsCount) 
{
$this->windowsCount = $windowsCount;
$this->wallsColor = $wallsColor;
$this->roomsCount = $roomsCount;
}
}
 $windowsCount = 10; 
 $wallsColor = “red”; 
 $roomsCount = 3; 
 $myBuilding = new Building($windowsCount, $wallsColor, $roomsCount); 

您刚刚看到了依赖注入在起作用!

如果看起来有点不知所措,请允许我解释发生了什么。

构造函数需要3个参数: $ windowsCount,$ wallsColor$ roomsCount

调用此方法后,将使用以下三种方法将这3个参数:

$ this-> nameOfTheVariable = $ nameOfTheParamether;

创建新对象(在我们的示例中为$ myBuilding)时,将在括号内指定三个参数:

$ myBuilding =新建筑物($ windowsCount,$ wallsColor,$ roomsCount);

需要牢记的一个非常重要的注意事项是,两个地方的参数顺序必须相同,否则在带有1个房间的建筑物中,可能会导致$ roomCount等于红色和50个窗口。

做得好!

但是我们还没有完成。

我们可以实现此技术,以进行一些改进以提高代码质量。

这里是对它们的简要说明。

可选参数

一旦设置了类或方法并要求依赖,就必须提供一个参数,以免发生错误,但是如果没有必需的参数该怎么办?

好了,您可以通过为其设置默认值来预先建立它。

怎么样?

...
 function __construct($wallsColor = red) 
{
...
}
 $myRedBuilding = new Building(); 
 $myBlueBuilding = new Building(“blue”); 

此处创建的两个对象之间的主要区别是。

目前,我们创建第一个对象时,我们没有提供任何参数,但是我们要确保人们不会只看到砖头和混凝土,因此我向构造函数添加了默认值,以通过$ wallsColor = red做到这一点

这段代码所说的文学作品是:

如果没有参数指定此建筑物中墙壁的颜色,请使用默认的红色。

在第二个对象中,您可以看到括号内的蓝色字符串,并且“ blue”将覆盖红色的标准颜色。

类型提示

什么是类型提示?

类型提示是一种明确指出所需数据类型(对象,接口等)的做法。

从PHP5的早期版本到新版本,都可以在方法内部键入提示参数。

像这样:

 function __construct(array $address) 
{
...
}
 $address = [ 
'main street',
'248',
'London'
];
 $myBuilding = new Building($address); 

现在,构造函数需要一个数组类型的地址变量。

如果放置不是数组的所有内容,将导致错误。

此过程非常有用,因为它增加了新的保护级别,从而提高了安全性并提供了更好的代码。

PHP7的新功能是现在甚至可以执行标量类型提示,这意味着,如果使用最新版本PHP,则可以提示布尔值。 字符串,整数和浮点变量。

__destruct()方法

您已经看到,构造函数是实例化新对象时调用的第一个方法,

从逻辑上讲,最后调用的魔术方法的名称是解构函数。

当对象没有更多引用或强制删除时,将自动调用此方法。

您很少会看到这种方法,但是从我的角度来看,它非常有用,因为PHP会清理对象并将其从内存中删除,从而提高了性能。

 function __destruct() { 
     echo "The building has been terminated"; 
}

__call()和__callStatic()方法

这些调用方法非常容易理解。

如果类具有__call()方法(请不要忘记双下划线),并且您调用了对象上不存在的方法,则将调用__call()方法。

 class Building 
{
     function __call($method, $arguments) 
{
         echo _CLASS_ . “has not method ” . $method; 
}
}
 $myHome = new Building(); 
$myHome->buyAWindow();
// This code will echo the sentence in __call() method
// "Building has not method buyAWindow"

上面的示例中的类没有buyAWindow()方法,因此,在这种情况下,将调用__call()方法并返回消息。

__call()__callStatic()方法之间的唯一区别是,第一个响应非静态调用,第二个响应静态调用。

请注意,

即使我没有指定任何参数,调用方法也将方法的名称指定为第一个,而将包含参数列表的数组用作第二个参数。

getter和setter方法

当代码尝试读取或写入类中不存在或不可用的属性时,将调用__get()__set()方法。

 class Building 
{
     function __get($propertyName) 
{
         echo $propertyName . “does not exists”; 
}
     function __set($propertyName, $propertyValue) 
{
         echo “Impossible to set ” . $propertyValue . “to ” . $propertyName; 
}
}
 $myHome = new Building(); 
 echo $myHome->securityCameraCount; 
// It will echo the string “securityCameraCount does not exists”
$myHome->televisionCount = 10;
// It will echo the string “Impossible to set televisionCount to 10”

在上面的示例中, $ securityCameraCount()是Building类中不存在的方法,

__get()方法已传递了要查找的属性的名称,因此我们可以通过返回一个警告用户的字符串来管理此错误。

我们对TelevisionCount有相同的问题,

该参数在该类中不可用,因此当我们尝试为其分配值10时,PHP会理解它需要调用__set()方法,

在setter方法中,您可以根据自己的选择进行选择,最常见的管理方法是通过消息向用户显示错误。

toString()方法

有时可能会由于错误或有意将类视为字符串而发生。

例如,当这样做时:

 $myHome = new Building(); 
 echo $myHome; 

__toString()方法允许您管理发生这种情况时的类行为。

这被认为是一种非常精致的方法,因为如果您编写错误的代码,它很容易引发致命错误。

例如,

这个魔术方法必须返回一个字符串,并且您不得从内部抛出异常,如果不遵守这些条件之一,PHP将返回致命错误。

您可以在下面看到__toString()方法的完整示例。

 class Building 
{
     public $sentence; 
     public function __toString() 
{
         return $this->sentence; 
}
}
 $myHome = new Building(); 
 echo $myHome; 

__sleep()和__wakeup()夫妇

当对象被序列化或未序列化时,将调用这两种方法。

确切地说, __ sleep()在序列化之前被调用。

而__wakeup()在反序列化之后会被调用一点。

它们如何运作?

serialize()方法检查调用中是否存在魔术方法__sleep(),如果存在,serialize()会停止一秒钟,然后让__sleep()进行操作。

由于此方法必须返回一个数组,因此通常其目标是返回一个数组,其中包含所有需要序列化的对象变量的名称。

如果该方法不返回任何内容,则返回的是被序列化的NULL并将显示E_NOTICE。

合理使用此方法的一些有用案例可能是获取不需要保存的大型对象数据或执行某些清理工作。

另一方面,您具有__wakeup()方法。

它只是反映了他的密友__sleep(),

这次是unserialize()方法来查找__wakeup(),如果它存在于类中,则该方法将还原序列化过程中丢失的所有数据连接。

 class Building 
{
     public $address, $city, $postcode; 
     public function __sleep() 
{
         return array(address', 'city, 'postcode); 
}
     public function __wakeup() 
{
         return $address; 
}
}

__invoke()方法

__invoke()方法非常简单,

当代码确实是调用方法或函数时,将自动调用它。

 class Building 
{
     public function __invoke($variable) 
{
var_dump($variable);
}
}
 $myBuilding = new Building ; 
$myBuilding(“23, Main Street”);

在上面的示例中,invoke方法的结果将显示string(15)“ 23,Main Street”

在线上有很多有关如何使用此方法的示例,但您可以根据需要选择实现此方法的最佳方法。

可以将此方法视为一种捷径,使您可以执行特定任务,并且可以通过将该对象作为一种方法来访问。

这种魔术方法相当宽松,这意味着您几乎可以用它来做任何想做的事,但要注意一件事,参数和参数需要匹配,

如果调用对象并设置4个参数,则连接的方法需要具有4个参数。

忘记执行此操作将导致脚本引发错误。

__set_state()和var_export

我们只是从一种更容易理解的魔术方法变成了最复杂的魔术方法之一。__set_state()方法是在将对象的实例传递给var_export函数时发生的。

var_export()是做什么的?

它返回一个表示变量的可分析字符串,它与var_dump()非常相似,但是返回的值是有效PHP代码。

var_export()需要两个参数,

第一个是强制性的,需要表示您需要导出的变量,而第二个是可选的布尔值,指示是否必须将变量表示形式返回为字符串或将其输出。

我们在这里需要一个样本:

 class Building 
{
    public $windowsCount; 
}
 $myBuilding = new Building; 
$myBuilding->windowsCount = 5;
var_export($myBuilding);
// This code will output:
Building::__set_state(array(
windowsCount => 5,
))

现在__set_state(),

如前所述,调用__set_state()来响应传递给var_export函数的对象的实例。

它只有一个参数,该参数必须是包含导出的属性作为键值对的数组。

 class Building 
{
     public $windowsCount; 
     public static function __set_state($windows) 
{
         $myBuilding = new Building; 
$myBuilding>windowsCount = $windows['windowsCount'];
         return $myBuilding; 
}
}
 $myBuilding = new Building; 
$myBuilding->windowsCount = 5;
 eval('$state = ' . var_export($a, true) . ';'); 
/*
$state = Building::__set_state(array(
'windowsCount' => 5,
));
*/
var_dump($state);

它将导致:

object(Building)#2 (1) {
["windowsCount"]=> int(5)
}

使用__debuginfo()进行调试

PHP 5.6附带了此特性,当您转储对象以确定需要输出哪些属性时,此特性由var_dump()调用。

如果未在对象上定义该方法,则将显示所有公共,受保护和私有属性。

 class Building { 
     private $windows; 
     private $doors; 
     public function __debugInfo() { 
         return [ 
             'windows' => $this->windows, 
];
}
}
 var_dump(new Building(10)); 
// Here is the outcome
object(Building)#1 (1) {
["'windows'"]=> int(10)
}

在上面的示例中,我们说__debugInfo()只需要返回$ windows并隐藏$ doors

第五部分结论

名词解释: oop_OOP中的魔术方法:权威指南(PHP)_第2张图片

无论何时,以下部分将以 Kindle格式在Kindle上提供完整版的“面向对象编程的完整指南”的完整版本

我希望您现在更多地了解PHP语言必须提供给Web开发人员的所有方法和技巧。

您可能不会每天使用上述方法,

但,

一旦您了解了这些概念,并可能不时返回此页面以了解其目的,将有助于您更好地管理代码。

另外,请注意,您仅需要将它们视为帮助者。

即使没有人可以否认自己的能力,开始使用call方法,getter,setter等最终将使您对正在编写的项目的控制较少。

您的主要重点必须是编写可扩展的干净代码,并让您执行所需的操作,反之亦然。

说,

在深入了解它们在幕后的工作方式之后,请放心,不要害怕利用依赖注入,构造函数和其他方法。

在下一集中

您将看到什么是抽象方法以及与面向对象范例相关的其他功能。

所以,

请继续关注并使用此处的表单进行订阅,以在发布时得到通知。

现在轮到您了:

您是否要使用受保护的和私有关键字来更新方法和属性,还是更喜欢在各处传播静态关键字?
在下面的评论框中让我知道!

在下一集中

我们将专注于魔术方法

我准备了完整的列表,其中包含详细的描述和代码示例。

为此原因,

请继续关注并使用此处的表单进行订阅,以在发布时得到通知。

现在轮到您了:

您打算在代码中实现什么魔术方法?
在下面的评论框中让我知道!

如果您喜欢此内容,并且渴望更多,请 加入Facebook社区 ,我们在其中共享信息和新闻。

翻译自: https://hackernoon.com/magic-methods-in-oop-the-definitive-guide-php-e3f8a0da278

名词解释: oop

你可能感兴趣的:(python,java,编程语言,php,linux)