![](https://i-blog.csdnimg.cn/blog_migrate/7c618bb343ada52643d6a8e31d5ddacc.png)
介绍
很久很久以前,
曾经有一位Web开发人员花了数周和数周的时间来更新相同的代码行。
这使他头疼得很厉害。
有一天,在博客文章之间浏览时,他遇到了“面向对象编程”一词,接下来发生的事情令人惊讶……
从其简单的语法到以一种直接但仍有效的方式重用相同代码的优点。
今天,您将学习如何最好地管理这些对象,以及如何使用继承和接口在它们之间建立长期安全的关系。
遗产
什么是OOP继承?
需要精通继承,封装,抽象和多态性,以精通编程并真正提高技能。
继承所做的是在父子模型中将类彼此关联。
当相关类必须具有相同的提取特征并允许实现其他方法和属性而无需再次重写它们时,这非常有用。
![](https://i-blog.csdnimg.cn/blog_migrate/ec811b65c6013d2b47746281160e2453.png)
就像上一篇文章一样,我们仍然以Building类为例,
在此示例中,我们假设当您要实例化新建筑物时,建造该建筑物的工作已经完成并且向公众开放。
class
Building
{
$inConstruction
= false;
$isOpen
= true;
function
closeBuilding()
{
return
$this->isOpen = false;
}
function
openBuilding()
{
return
$this->isOpen = true;
}
}
class
School extends
Building
{
}
class
Office extends
Building
{
$isOpen
= false;
}
我们这里有三节课,
父类是Building类,其子类继承了建筑要素,属性和方法。
现在,我们可以实例化特定的学校和办公室,而不是实例化的抽象建筑
$mySchool
= new
School();
$myOffice
= new
Office();
echo
$myShool->closeBuilding(); // The output will be “false” because of the parent Building
echo
$myOffice->isOpen; // The output will be “false” because of the child Office
如您所见,我实际上并未在School类中编写任何内容,但它仍继承了其父类Building的所有属性和方法。
此原则称为DRY(不要重复自己),其目的是减少我们一次又一次编写的文本。
我确定您也注意到Office类在$ isOpen变量上的值与其父类不同,
事实上,
通过将父项的相同属性或方法写入子项,我们将覆盖其功能。
基本上,
当实例化的$ myOffice关闭时, $ mySchool遵循Building的行为并保持$ isOpen保持为false( $ mySchool开放供访问)。
为什么要使用继承?
关于此主题有几种想法,
有人说继承是件好事,如果您只是想在实际项目中使用它,那么一些高级开发人员会杀死您,
我认为,在大多数情况下,真理停留在中间。
继承是一种节省时间的绝佳方法,可以避免一遍又一遍地写相同的东西 ,
它非常容易理解,对于OOP的新手来说,这是正确的选择。
的确, 继承有几个局限性 ,对于经验丰富的Web开发人员来说,还有很多更好的选择,一个就是所有。
观看来自Fun Fun Function的视频
![](https://i-blog.csdnimg.cn/blog_migrate/027387c84fe70553bd13ea8eaf7df981.png)
我的建议是使用继承,只要您100%熟悉此技术,了解如何使用继承,何时使用它共享功能以及何时使用其他技术(例如合成,设计模式)(工厂模式是真正的结束语),甚至只是向类添加一个特征。
extend关键字
没有人知道为什么创建继承的关键字不是继承或更一致,更容易记住的东西,但我们在这里。
为了允许一个类从另一个类继承,我们需要在子类名称之后和左括号之前指定关键字“ extends”和父类。
![](https://i-blog.csdnimg.cn/blog_migrate/a8c42bce715f0dfa7407f8bcb90b0532.png)
需要注意的一种情况是,子类必须始终仅依赖于单个父类,这意味着不支持多个继承。
以这种方式思考:
我们在前面的示例中使用的Office类不能同时继承Building类和Animal类的要素。
它们只是没有共同点。
“最终”关键字
最后一个关键字是在php5中首次引入的非常简单的概念。
简单来说
它防止方法或类被扩展。
让我们来看一个简单的例子。
假设我们虚构的城市的市长决定所有建筑物都必须至少有一个紧急出口,现在看下面的代码示例。
class
Building
{
...
function
setFireExtinguisher()
{
$this->fireExtinguisherCount = 1;
}
}
classOffice extends
Building
{
function
setFireExtinguisher()
{
$this->fireExtinguisheCount = 0;
}
}
在这种情况下,
Office类的setFireExtinguisher()方法已覆盖Building类,并将fireExtinguisheCount设置为0,
市长认为这是非法的。
防止这种情况发生的一种方法,可以避免建筑师为了将final关键字添加到方法而入狱。
class
Building
{
...
final
function
setFireExtinguisher()
{
$this->fireExtinguisherCount = 1;
}
}
class
Office extends
Building
{
function
setFireExtinguisher()
{
$this->fireExtinguisheCount = 0;
}
}
现在,无法使用Office类的setFireExtinguisher()方法的代码,实际上将导致致命错误“无法覆盖最终方法Building-> setFireExtinguisher()” 。
非常简单的概念,非常容易实现。
本文的这一部分只有一条规则:
您不能使用final on属性。
属性是变量,顾名思义,它们需要能够变化。
您可以在不希望扩展的类上使用final,也可以在不能覆盖的方法上使用final。
介面
建筑师和建造者为了建造建筑物需要遵循哪些强制性步骤?
尤其是在公共场所,需要遵守一些法规,例如我们添加一些急救,制定疏散计划等。
界面可让您提前安排此步骤,并强制类相应地实现它们。
如果类是对象的蓝图,可以用一种非常简单的方式将接口想像成类的蓝图。
将Interface视为一个纯模板。
让我解释,
为什么首先需要对象接口?
在PHP Interfaces中定义了一个类必须实现的方法,
同时,接口没有指定如何实现这些方法,
您很快就会看到,在管理课程时,最后一句话为您提供了很大的自由度。
“ interface”关键字
创建接口的语法与创建类的语法几乎相同,
命名接口通常遵循一些约定,这会使其他人更容易理解您的代码,最常用的约定是:
- ThingInterface;
- 东西
- I_Thing;
在以下示例中,我将创建将在Building类中使用的接口。
我们市已久负盛名的市长非常关心安全问题,他决定,我们市内的每栋建筑物都必须配备火灾报警器和防灾集结点。
让我们编写这些接口的代码。
interface
FireAlarmInterface
{
function
setFireAlarm();
}
interface
AssemblyPointInterface
{
function
setAssemblyPoint();
}
在上一小节中,您应该注意两件事:
第一个是接口看起来与类非常相似,
第二个原因是没有括号可以打开方法中的代码块,原因是接口并不能确定方法的实现方式,而只是确定需要实现的方法。
“实施”关键字
现在已经创建了接口,我们需要在Building类中实现它们。
要实现接口,您需要使用Implements关键字。
您必须注意的一个基本的特殊性是: 接口中的所有方法必须包含在实现接口的类中 。
这是强制性规则,也不例外。
如果在屏幕上抛出致命错误,PHP会告诉您是否忘记了方法。
class
Building implements
FireAlarmInterface
{
function
setFireAlarm()
{
$this->fireAlarm = true;
}
}
如前所述,接口中的所有方法都必须在一个类中实现。
否则将导致致命错误。
与继承不同,一个类可以实现多个接口。
事实上,
如果需要,可以列出所有接口,并列出它们,并用逗号分隔每个接口。
class
Building implements
FireAlarmInterface, AssemblyPointInterface
{
…
}
尽管这是PHP的一个非常令人印象深刻的功能,但让我再次强调一下,实现的每个接口的每个方法都必须包含在类中,这会导致很多混乱。
因此,请与您的接口保持一致,并在研究了所有可能发生的传入问题之后才使用它们。
PHP中包含的内置接口列表
PHP具有集成到该语言中的少数接口。
尽管它们中的大多数不太可能每天使用,但其中一些可能非常有用,并且肯定会在您的项目开发过程中为您节省一些时间。
可穿越
顾名思义, Traversable接口分析一个类并返回一个布尔值,具体取决于实现该可遍历的类是否使用foreach 。
该接口没有方法,其目的是成为可遍历类的基础。
Traversable {
}
您可以在条件语句中使用此接口来检查foreach是否有用。
这是一个简单的例子
if( $buildings
instanceof
Traversable ){
foreach
($buildings
as
$building){
…
}
}
请注意,该接口不适用于数组和对象,
这意味着您无法使用Traversable来检查是否可以在数组中使用这些类型的变量。
为什么您甚至首先需要验证它们?
迭代器
此接口适用于可以重复自身的对象或迭代器。
上面的句子只是意味着您可以将Iterator接口扩展到任何可遍历的元素,并在类上包括以下方法。
Iterator extends
Traversable {
function
current ()
{
}
function
key ()
{
}
function
next ()
{
}
function
rewind
()
{
}
function
valid ()
{
}
}
明白了吗?
这里有一个关于如何实际使用此接口的真实示例:
public
function
rewind()
{
$this->position = 0;
}
public
function
current() {
return
$this->array[$this->position];
}
public
function
key() {
return
$this->position;
}
public
function
next() {
++$this->position;
}
public
function
valid() {
return
isset($this->array[$this->position]);
}
IteratorAggregate
IteratorAggregate接口只是在代码中实现Iterator的另一种方法。
IteratorAggregate extends
Traversable {
function
getIterator ()
{
}
}
使用此界面的好处是速度快,
实际上, IteratorAggregate比其他选项要快得多,
您需要注意,尽管这个名字不是Iterator,但是它是Traversable 。
这意味着没有下一个,键,当前,有效,倒带方法可用。
可投掷
Throwable接口用于可通过throw语句抛出的所有对象,
它们包括错误和异常。
这是接口及其方法的完整列表:
interface
Throwable {
function
getMessage ()
{
}
function
getCode ()
{
}
function
getFile ()
{
}
function
getLine ()
{
}
function
getTrace ()
{
}
function
getTraceAsString ()
{
}
function
getPrevious ()
{
}
function
__toString ()
{
}
}
PHP无法直接实现此接口,
它只能通过Exception扩展。
第二部分总结
![](https://i-blog.csdnimg.cn/blog_migrate/1f368adcdee70488a673e2621f8bf6a6.png)
多合一版本的完整版“ 面向对象编程的完整指南 ”可在亚马逊上以Kindle格式获得。
但是,请放心,以下部分将在接下来的几周内发布。
…Web开发人员真正相信他的工作非常出色,老实说他是对的。
他已经能够创建出自己所有想法,可以从头开始创建应用程序,甚至可以创建使他的老板和客户满意的困难系统,
他意识到自己的领域是不停的学习,一件事情之后是另一件事,然后是另一件事,然后是另一件事。
今天你就像他,
您已经了解了OOP基础知识 ,现在又了解了一些关键字,明天您将吸收其他信息。
编程永无止境,您以为自己知道的越少,就会越了解。
您在开发知识的哪一部分?
您是否已经学到了一切,或者只是遵循OOP原则?
在下面的评论中让我知道...
如果您喜欢此内容,并且渴望更多,请 加入Facebook社区 ,我们在其中共享信息和新闻。
From: https://hackernoon.com/inheritance-and-interfaces-in-php-d46b61c65b84