PHP 面向对象编程
我们可以想象我们的宇宙由不同的对象组成,像太阳、地球、月亮等等。类似地,我们可以想象我们的汽车由轮子、方向盘、齿轮等不同的对象组成。同样地,面向对象编程概念将一切都视为对象,并使用不同的对象来实现软件。
面向对象概念
在我们深入讨论之前,先定义与面向对象编程相关的重要术语。
- 类 - 这是一种由程序员定义的数据类型,包含本地函数和本地数据。您可以将类看作是制造许多相同类型(或类)的对象实例的模板。
-
对象 - 由类定义的数据结构的单个实例。您只需定义一次类,然后创建许多属于该类的对象。对象也称为实例。
-
成员变量 - 这些是定义在类内部的变量。这些数据对类的外部是不可见的,但可以通过成员函数来访问。一旦创建了对象,这些变量就称为对象的属性。
-
成员函数 - 这些是在类内部定义的函数,用于访问对象数据。
-
继承 - 当一个类通过继承现有的父类函数来定义时,就被称为继承。子类将继承父类的所有或部分成员函数和变量。
-
父类 - 被另一个类继承的类。这也称为基类或超类。
-
子类 - 继承另一个类的类。这也称为子类或派生类。
-
多态 - 这是面向对象的一个概念,同一个函数可以用于不同的目的。例如,函数名称保持不变,但接受不同数量的参数并可以执行不同的任务。
-
重载 - 这是一种多态性,其中一些或所有操作符根据其参数类型具有不同的实现。类似地,函数也可以使用不同的实现进行重载。
-
数据抽象 - 任何表示数据的方式,其中隐藏了实现细节(抽象化)。
-
封装 - 指的是将所有的数据和成员函数封装在一起形成一个对象的概念。
-
构造函数 - 指的是一种特殊类型的函数,当从一个类中形成对象时,会自动调用该函数。
-
析构函数 - 指的是一种特殊类型的函数,当一个对象被删除或超出范围时,会自动调用该函数。
定义PHP类
在PHP中定义一个新类的一般形式如下:
以下是每行的说明:
- 特殊形式 class ,后面跟着你要定义的类的名称。
-
一对大括号,内部包含任意数量的变量声明和函数定义。
-
变量声明以特殊形式 var 开头,后面跟着一个常规的$变量名;它们也可以有初始赋值给一个常量值。
-
函数定义看起来很像独立的PHP函数,但是它们是局部的类函数,用于设置和访问对象数据。
示例
以下是一个定义了Books类型的类的示例:
变量 $this
是一个特殊的变量,它指的是同一个对象,即它本身。
在PHP中创建对象
一旦你定义了类,你就可以创建多个属于该类类型的对象。下面是使用 new 操作符创建对象的示例。
在这里,我们创建了三个对象,这些对象是相互独立的,它们将分别存在。接下来,我们将看到如何访问成员函数和处理成员变量。
调用成员函数
创建对象后,您将能够调用与该对象相关的成员函数。一个成员函数只能处理其相关对象的成员变量。
以下示例展示了如何通过调用成员函数为这三本书设置标题和价格。
现在你调用另一个成员函数来获取上面示例中设置的值 –
这将产生以下结果−
构造函数
构造函数是一种特殊类型的函数,当对象被创建时会自动调用。因此,我们通过构造函数可以初始化许多事物。
PHP提供了一个特殊的函数称为 __construct()
来定义一个构造函数。您可以在构造函数中传递任意多个参数。
以下示例将为Books类创建一个构造函数,并在对象创建时初始化图书的价格和标题。
现在我们不需要分别调用set函数来设置价格和标题。我们只需要在对象创建时初始化这两个成员变量。请查看以下示例−
这将产生以下结果 −
析构函数
类似于构造函数,您可以使用函数 __destruct() 来定义析构函数。您可以在析构函数中释放所有资源。
继承
PHP类定义可以选择性地通过使用extends子句从父类定义中继承。语法如下所示 –
继承的影响是子类(或子类或派生类)具有以下特点 −
- 自动具有父类的所有成员变量声明。
-
自动具有与父类相同的所有成员函数,默认情况下这些函数的工作方式与父类中的函数相同。
以下示例继承了Books类,并根据需求添加了更多功能。
现在除了继承的函数之外,类Novel还保留了两个额外的成员函数。
函数重写
子类中的函数定义会覆盖父类中相同名称的定义。在子类中,我们可以修改从父类继承的函数的定义。
在下面的示例中,getPrice和getTitle函数被重写以返回一些值。
公共成员
除非您另行指定,类的属性和方法都是公共的。也就是说,它们可以在以下三种情况下访问:
- 在声明该类之外的地方
-
在声明该类的内部
-
在实现该类的另一个类的内部
到目前为止,我们已经把所有成员都视为公共成员。如果您希望限制类的成员的可访问性,那么您可以将类成员定义为 私有 或 受保护 。
私有成员
通过将成员指定为私有,您限制了它只能在声明它的类中访问。私有成员不能从继承该类的类中引用,也不能从类外部访问。
可以使用 private 关键字将类成员设置为私有成员。
当另一个类使用extends继承MyClass类时,myPublicFunction()和car,因为它们被声明为私有。
保护成员
受保护的属性或方法可在声明它的类中访问,以及扩展该类的类中访问。受保护的成员在这两种类型的类之外不可用。通过在成员前面使用 protected 关键字,可以将类成员设置为受保护。
这是MyClass的另一个版本 –
接口
接口是为实现者提供共同的函数名称。不同的实现者可以根据自己的需求实现这些接口。可以说,接口是由开发人员实现的骨架。
从PHP5开始,可以像这样定义一个接口−
然后,如果另一个类实现了该接口,就像这样 –
常量
常量有点像变量,因为它保存一个值,但更像一个函数,因为常量是不可变的。一旦声明了一个常量,它就不会改变。
声明一个常量很简单,就像在这个版本的MyClass中做的一样−
在这个类中,requiredMargin是一个常量。它使用关键字const声明,在任何情况下都不能改变为除了1.7之外的其他值。注意,常量的名称没有前导的$,和变量的名称不同。
抽象类
抽象类是不能被实例化的,只能被继承。你可以使用关键字 abstract 来声明一个抽象类,如下所示:
当继承一个抽象类时,父类声明中所有标记为抽象的方法必须由子类来定义;此外,这些方法必须具有相同的可见性。
注意,在抽象类中定义的函数也必须以abstract关键字开头。在非抽象类中定义抽象函数是不合法的。
静态关键字
将类成员或方法声明为静态可以在不实例化类的情况下访问它们。声明为静态的成员不能使用实例化的类对象访问(但静态方法可以)。
尝试下面的示例 −
Final关键字
PHP 5引入了final关键字,通过在方法定义前加上final来阻止子类覆盖方法。如果类本身被定义为final,则无法被继承。
以下示例会导致致命错误:无法覆盖BaseClass::moreTesting()的final方法。
调用父构造函数
不需要为子类编写全新的构造函数,我们可以通过显式调用父类的构造函数来编写子类的构造函数,并在子类实例化时进行其他必要的操作。这里是一个简单的示例:
在这个示例中,我们有一个父类(Name),它有一个带有两个参数的构造函数,还有一个子类(NameSub1),它有一个带有三个参数的构造函数。NameSub1的构造函数通过使用::语法显式调用其父类构造函数(传递两个参数),然后设置一个额外的字段。类似地,NameSub1通过覆盖的父类函数来定义它的非构造函数toString()函数。
注意 - 构造函数可以使用与类名相同的名称进行定义。在上面的示例中已经定义了。