- PHP 教程
- PHP - 首页
- PHP - 简介
- PHP - 安装
- PHP - 历史
- PHP - 特性
- PHP - 语法
- PHP - Hello World
- PHP - 注释
- PHP - 变量
- PHP - Echo/Print
- PHP - var_dump
- PHP - $ 和 $$ 变量
- PHP - 常量
- PHP - 魔术常量
- PHP - 数据类型
- PHP - 类型转换
- PHP - 类型杂耍
- PHP - 字符串
- PHP - 布尔值
- PHP - 整数
- PHP - 文件与 I/O
- PHP - 数学函数
- PHP - Heredoc 和 Nowdoc
- PHP - 复合类型
- PHP - 文件包含
- PHP - 日期和时间
- PHP - 标量类型声明
- PHP - 返回类型声明
- PHP 运算符
- PHP - 运算符
- PHP - 算术运算符
- PHP - 比较运算符
- PHP - 逻辑运算符
- PHP - 赋值运算符
- PHP - 字符串运算符
- PHP - 数组运算符
- PHP - 条件运算符
- PHP - 展开运算符
- PHP - 空值合并运算符
- PHP - 比较运算符
- PHP 控制语句
- PHP - 决策
- PHP - If...Else 语句
- PHP - Switch 语句
- PHP - 循环类型
- PHP - For 循环
- PHP - Foreach 循环
- PHP - While 循环
- PHP - Do...While 循环
- PHP - Break 语句
- PHP - Continue 语句
- PHP 函数
- PHP - 函数
- PHP - 函数参数
- PHP - 按值传递
- PHP - 按引用传递
- PHP - 默认参数
- PHP - 命名参数
- PHP - 可变参数
- PHP - 返回值
- PHP - 传递函数
- PHP - 递归函数
- PHP - 类型提示
- PHP - 变量作用域
- PHP - 严格类型
- PHP - 匿名函数
- PHP - 箭头函数
- PHP - 可变函数
- PHP - 局部变量
- PHP - 全局变量
- PHP 超全局变量
- PHP - 超全局变量
- PHP - $GLOBALS
- PHP - $_SERVER
- PHP - $_REQUEST
- PHP - $_POST
- PHP - $_GET
- PHP - $_FILES
- PHP - $_ENV
- PHP - $_COOKIE
- PHP - $_SESSION
- PHP 文件处理
- PHP - 文件处理
- PHP - 打开文件
- PHP - 读取文件
- PHP - 写入文件
- PHP - 文件是否存在
- PHP - 下载文件
- PHP - 复制文件
- PHP - 追加文件
- PHP - 删除文件
- PHP - 处理 CSV 文件
- PHP - 文件权限
- PHP - 创建目录
- PHP - 列出文件
- 面向对象 PHP
- PHP - 面向对象编程
- PHP - 类和对象
- PHP - 构造函数和析构函数
- PHP - 访问修饰符
- PHP - 继承
- PHP - 类常量
- PHP - 抽象类
- PHP - 接口
- PHP - 特性
- PHP - 静态方法
- PHP - 静态属性
- PHP - 命名空间
- PHP - 对象迭代
- PHP - 封装
- PHP - Final 关键字
- PHP - 重载
- PHP - 克隆对象
- PHP - 匿名类
- PHP Web 开发
- PHP - Web 概念
- PHP - 表单处理
- PHP - 表单验证
- PHP - 表单邮件/URL
- PHP - 完整表单
- PHP - 文件包含
- PHP - GET 和 POST
- PHP - 文件上传
- PHP - Cookies
- PHP - Sessions
- PHP - Session 选项
- PHP - 发送邮件
- PHP - 过滤输入
- PHP - Post-Redirect-Get (PRG)
- PHP - 闪存消息
- PHP 高级
- PHP - MySQL
- PHP.INI 文件配置
- PHP - 数组解构
- PHP - 编码规范
- PHP - 正则表达式
- PHP - 错误处理
- PHP - Try...Catch
- PHP - Bug 调试
- PHP - 适用于 C 开发人员
- PHP - 适用于 PERL 开发人员
- PHP - 框架
- PHP - Core PHP 与框架
- PHP - 设计模式
- PHP - 过滤器
- PHP - JSON
- PHP - 异常
- PHP - 特殊类型
- PHP - 哈希
- PHP - 加密
- PHP - is_null() 函数
- PHP - 系统调用
- PHP - HTTP 认证
- PHP - 交换变量
- PHP - Closure::call()
- PHP - 过滤的 unserialize()
- PHP - IntlChar
- PHP - CSPRNG
- PHP - 预期
- PHP - Use 语句
- PHP - 整数除法
- PHP - 已弃用的特性
- PHP - 已删除的扩展和 SAPI
- PHP - PEAR
- PHP - CSRF
- PHP - FastCGI 进程
- PHP - PDO 扩展
- PHP - 内置函数
- PHP 有用资源
- PHP - 速查表
- PHP - 问答
- PHP - 快速指南
- PHP - 在线编译器
- PHP - 有用资源
- PHP - 讨论
PHP 面向对象编程
我们可以想象我们的宇宙是由不同的物体组成的,比如太阳、地球、月亮等等。同样,我们可以想象我们的汽车是由不同的物体组成的,比如车轮、方向盘、齿轮等等。同样,存在面向对象编程的概念,它假设一切都是对象,并使用不同的对象来实现软件。
面向对象概念
在我们深入了解之前,让我们定义一些与面向对象编程相关的术语。
类 - 这是程序员定义的数据类型,它包括局部函数和局部数据。您可以将类视为创建许多相同类型(或类)对象的模板。
对象 - 类定义的数据结构的单个实例。您只定义一次类,然后创建许多属于它的对象。对象也称为实例。
成员变量 - 这些是在类中定义的变量。此数据对类外部不可见,并且可以通过成员函数访问。一旦创建对象,这些变量就被称为对象的属性。
成员函数 - 这些是在类中定义的函数,用于访问对象数据。
继承 - 当一个类通过继承父类的现有函数来定义时,它被称为继承。这里子类将继承父类所有或部分成员函数和变量。
父类 - 被另一个类继承的类。这也被称为基类或超类。
子类 - 从另一个类继承的类。这也被称为子类或派生类。
多态性 - 这是一个面向对象的概念,其中相同的函数可以用于不同的目的。例如,函数名将保持不变,但它可以接受不同数量的参数并执行不同的任务。
重载 - 多态性的一种类型,其中某些或所有运算符具有不同的实现,具体取决于其参数的类型。类似地,函数也可以通过不同的实现进行重载。
数据抽象 - 任何隐藏(抽象)实现细节的数据表示。
封装 - 指的是一个概念,我们将所有数据和成员函数封装在一起以形成一个对象。
构造函数 - 指的是一种特殊类型的函数,每当从类中形成对象时,它都会自动被调用。
析构函数 - 指的是一种特殊类型的函数,每当对象被删除或超出范围时,它都会自动被调用。
定义 PHP 类
在 PHP 中定义新类的通用形式如下所示:
<?php class phpClass { var $var1; var $var2 = "constant string"; function myfunc ($arg1, $arg2) { [..] } [..] } ?>
以下是每行的描述:
特殊的class形式,后跟要定义的类的名称。
一组花括号,包含任意数量的变量声明和函数定义。
变量声明以特殊的var形式开头,后跟传统的$变量名;它们也可以具有对常量的初始赋值。
函数定义看起来很像独立的 PHP 函数,但它们是局部于类的,将用于设置和访问对象数据。
示例
这是一个定义 Books 类型的类的示例:
<?php class Books { /* Member variables */ var $price; var $title; /* Member functions */ function setPrice($par){ $this->price = $par; } function getPrice(){ echo $this->price ."<br/>"; } function setTitle($par){ $this->title = $par; } function getTitle(){ echo $this->title ." <br/>"; } } ?>
变量$this是一个特殊变量,它指的是同一个对象,即自身。
在 PHP 中创建对象
定义类后,您可以根据该类类型创建任意数量的对象。以下是如何使用new运算符创建对象的示例。
$physics = new Books; $maths = new Books; $chemistry = new Books;
这里我们创建了三个对象,这些对象彼此独立,它们将分别存在。接下来,我们将了解如何访问成员函数和处理成员变量。
调用成员函数
创建对象后,您将能够调用与该对象相关的成员函数。一个成员函数只能处理相关对象的成员变量。
以下示例显示了如何通过调用成员函数为三本书设置标题和价格。
$physics->setTitle( "Physics for High School" ); $chemistry->setTitle( "Advanced Chemistry" ); $maths->setTitle( "Algebra" ); $physics->setPrice( 10 ); $chemistry->setPrice( 15 ); $maths->setPrice( 7 );
现在,您可以调用另一个成员函数来获取在上例中设置的值:
$physics->getTitle(); $chemistry->getTitle(); $maths->getTitle(); $physics->getPrice(); $chemistry->getPrice(); $maths->getPrice();
这将产生以下结果:
Physics for High School Advanced Chemistry Algebra 10 15 7
构造函数
构造函数是特殊类型的函数,每当创建对象时都会自动调用。因此,我们可以充分利用这种行为,通过构造函数初始化许多东西。
PHP 提供了一个名为__construct()的特殊函数来定义构造函数。您可以将任意数量的参数传递到构造函数中。
以下示例将为 Books 类创建一个构造函数,它将在对象创建时初始化书籍的价格和标题。
function __construct( $par1, $par2 ) { $this->title = $par1; $this->price = $par2; }
现在,我们不需要单独调用 set 函数来设置价格和标题。我们只可以在创建对象时初始化这两个成员变量。请查看下面的示例:
$physics = new Books( "Physics for High School", 10 ); $maths = new Books ( "Advanced Chemistry", 15 ); $chemistry = new Books ("Algebra", 7 ); /* Get those set values */ $physics->getTitle(); $chemistry->getTitle(); $maths->getTitle(); $physics->getPrice(); $chemistry->getPrice(); $maths->getPrice();
这将产生以下结果:
Physics for High School Advanced Chemistry Algebra 10 15 7
析构函数
像构造函数一样,您可以使用函数__destruct()定义析构函数。您可以在析构函数中释放所有资源。
继承
PHP 类定义可以通过使用 extends 子句从父类定义继承。语法如下:
class Child extends Parent { <definition body> }
继承的效果是子类(或子类或派生类)具有以下特征:
自动拥有父类所有成员变量声明。
自动拥有与父类相同的成员函数,这些函数(默认情况下)将以与父类中相同的方式工作。
以下示例继承 Books 类并根据需求添加更多功能。
class Novel extends Books { var $publisher; function setPublisher($par){ $this->publisher = $par; } function getPublisher(){ echo $this->publisher. "<br />"; } }
现在,除了继承的函数外,Novel 类还保留了两个额外的成员函数。
函数重写
子类中的函数定义会覆盖父类中同名函数的定义。在子类中,我们可以修改从父类继承的函数的定义。
在下面的例子中,getPrice 和 getTitle 函数被重写以返回一些值。
function getPrice() { echo $this->price . "<br/>"; return $this->price; } function getTitle(){ echo $this->title . "<br/>"; return $this->title; }
公有成员
除非你另行指定,否则类的属性和方法都是公有的。也就是说,它们可以在三种情况下被访问:
从声明它的类的外部
从声明它的类的内部
从实现声明它的类的另一个类中
到目前为止,我们看到的都是公有成员。如果你希望限制类成员的可访问性,那么你可以将类成员定义为私有或受保护。
私有成员
通过将成员指定为私有,你可以将其可访问性限制在声明它的类中。私有成员不能被继承声明它的类的类引用,也不能从类外部访问。
可以使用private关键字放在成员前面,将类成员设为私有。
class MyClass { private $car = "skoda"; $driver = "SRK"; function __construct($par) { // Statements here run every time // an instance of the class // is created. } function myPublicFunction() { return("I'm visible!"); } private function myPrivateFunction() { return("I'm not visible outside!"); } }
当MyClass类被另一个类使用extends继承时,myPublicFunction()将可见,$driver也可见。扩展类将无法感知或访问myPrivateFunction和$car,因为它们被声明为私有的。
受保护成员
受保护的属性或方法可以在声明它的类中访问,以及在扩展该类的类中访问。受保护的成员在上述两种类之外是不可用的。可以使用protected关键字放在成员前面,将类成员设为受保护的。
以下是MyClass的不同版本:
class MyClass { protected $car = "skoda"; $driver = "SRK"; function __construct($par) { // Statements here run every time // an instance of the class // is created. } function myPublicFunction() { return("I'm visible!"); } protected function myPrivateFunction() { return("I'm visible in child class!"); } }
接口
接口被定义为为实现者提供通用的函数名称。不同的实现者可以根据自己的需求实现这些接口。你可以说,接口是开发人员实现的骨架。
从PHP5开始,可以像这样定义一个接口:
interface Mail { public function sendMail(); }
然后,如果另一个类实现了该接口,像这样:
class Report implements Mail { // sendMail() Definition goes here }
常量
常量有点像变量,因为它保存了一个值,但实际上更像一个函数,因为常量是不可变的。一旦你声明了一个常量,它就不会改变。
声明一个常量很容易,就像在这个版本的MyClass中所做的那样:
class MyClass { const requiredMargin = 1.7; function __construct($incomingValue) { // Statements here run every time // an instance of the class // is created. } }
在这个类中,requiredMargin是一个常量。它用关键字const声明,在任何情况下都不能更改为除1.7以外的任何值。请注意,常量的名称前面没有$符号,变量名有。
抽象类
抽象类是指不能被实例化,只能被继承的类。你可以用关键字abstract声明一个抽象类,像这样:
当继承抽象类时,父类声明中标记为抽象的所有方法都必须由子类定义;此外,这些方法必须使用相同的作用域定义。
abstract class MyAbstractClass { abstract function myAbstractFunction() { } }
请注意,抽象类中的函数定义也必须以关键字abstract开头。在非抽象类中,不允许有抽象函数定义。
Static关键字
将类成员或方法声明为静态,使其无需实例化类即可访问。声明为静态的成员不能使用实例化的类对象访问(尽管可以使用静态方法)。
尝试以下示例:
<?php class Foo { public static $my_static = 'foo'; public function staticValue() { return self::$my_static; } } print Foo::$my_static . "\n"; $foo = new Foo(); print $foo->staticValue() . "\n"; ?>
Final关键字
PHP 5 引入了 final 关键字,它通过在定义前面加上 final 来阻止子类覆盖方法。如果类本身被定义为 final,则不能扩展它。
以下示例会导致致命错误:无法覆盖最终方法 BaseClass::moreTesting()
<?php class BaseClass { public function test() { echo "BaseClass::test() called<br>"; } final public function moreTesting() { echo "BaseClass::moreTesting() called<br>"; } } class ChildClass extends BaseClass { public function moreTesting() { echo "ChildClass::moreTesting() called<br>"; } } ?>
调用父构造函数
与其为子类编写一个全新的构造函数,不如通过显式调用父构造函数,然后执行子类实例化所需的任何其他操作来编写它。这是一个简单的例子:
class Name { var $_firstName; var $_lastName; function Name($first_name, $last_name) { $this->_firstName = $first_name; $this->_lastName = $last_name; } function toString() { return($this->_lastName .", " .$this->_firstName); } } class NameSub1 extends Name { var $_middleInitial; function NameSub1($first_name, $middle_initial, $last_name) { Name::Name($first_name, $last_name); $this->_middleInitial = $middle_initial; } function toString() { return(Name::toString() . " " . $this->_middleInitial); } }
在这个例子中,我们有一个父类(Name),它有一个带两个参数的构造函数,还有一个子类(NameSub1),它有一个带三个参数的构造函数。NameSub1 的构造函数通过使用 :: 语法显式调用其父构造函数(传递其两个参数)然后设置一个额外的字段来工作。类似地,NameSub1 根据其覆盖的父函数定义其非构造函数 toString() 函数。
注意 - 构造函数可以用与类名相同的名称定义。在上面的例子中定义了它。