面向对象编程(OOP)引入了相当多的特性,使编程变得更加复杂.
封装,继承,多态是OOP的三要素,这些是过程式中的函数所没有的.
具体体现在:
- 1.封装: class/interface/public/protected/private
- 2.继承: extends/implements
- 3.多态: 方法重写/方法重载
新增的class和interface加入了新的变量作用域,即类和接口里代码块是函数所没有的作用域.
在这个作用域里,可以定义变量和函数这些类和接口的成员,并且支持使用public/protected/private关键字对这些成员进行访问控制.比如public表示允许外部访问,protected表示允许类及其子类访问,private表示只允许所在类内部访问。
而且OOP还引入了方法重写和方法重载这些多态特性,即:
- 方法重写:参数列表相同,方法体不同.
- 方法重载:参数列表不同,方法体不同.
方法重写依赖继承,是子类的方法覆盖父类的方法,要求方法名和参数列表相同.
方法重载不依赖继承,是同一个类中的两个或两个以上的同名方法,参数列表不同。
需要注意的是继承并重写的方法只能维持或放大访问权限,不能缩小.
比如父类protected方法在子类重载为public是可行的.
在PHP中,因为不允许存在多个同名方法,所以不支持C++/Java那样的方法重载.
但PHP提供了魔术方法(__call,__callStatic)用于间接实现方法重载.
PHP中方法重写并不要求参数相同.
PHP不支持多重继承(继承多个父类),但可以实现多个接口,也可以用trait特性间接支持多重继承.
功能一览
<?php
class A{//创建类A
//构造函数与析构函数
//构造函数 - 在创建对象时初始化对象, 即为对象成员变量赋初始值
function __construct() {
print "构造函数n<br />";
$this->name = "我是默认值<br />";
}
//析构函数 - 当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
function __destruct() {
print "销毁 " . $this->name . "n<br />";
}
//基础元素
//创建属性
public $a_a;
public $a_b='a_b';
//创建af方法
function af() {}
//创建常量
const constant = '常量值<br />';
function showConstant() {
echo self::constant . PHP_EOL;//打印常量,并加空格(代码中)
}
//访问权限
//公有的类成员可以在任何地方被访问。
public $public = 'Public';
//受保护的类成员则可以被其自身以及其子类和父类访问。
protected $protected = 'Protected';
//私有的类成员则只能被其定义所在的类访问。
private $private = 'Private';
// 声明一个公有的方法
public function MyPublic() { }
// 声明一个受保护的方法
protected function MyProtected() { }
// 声明一个私有的方法
private function MyPrivate() { }
//静态
//创建一个公开的静态方法
public static function aStaticMethod() {
// ...
echo "Hello<br />";
}
//创建公开的静态属性
public static $my_static = 'foo<br />';
public function staticValue() {
return self::$my_static;
}
}
class B extends A {//类B继承类A
}
//实例化A类 - 可供使用的对象()
$class_a = 'A';
$a = new $class_a();
//B类的实例化 - 可供使用的对象
$b = new B;
//打印HelloHello
A::aStaticMethod();
$a::aStaticMethod();//上面已实例化过
?>
名词解释
class
- 每个类的定义都以关键字
class
开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义。 - 类名可以是任何非 PHP 保留字 的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线。以正则表达式表示为:
^[a-zA-Z_x80-xff][a-zA-Z0-9_x80-xff]*$
。 - 一个类可以包含有属于自己的 常量,变量(称为“属性”)以及函数(称为“方法”)。
- 当一个方法在类定义内部被调用时,有一个可用的伪变量 $this。$this 是一个到当前对象的引用。
new
要创建一个类的实例,必须使用 new
关键字
属性和方法
类的属性和方法存在于不同的“命名空间”中,这意味着同一个类的属性和方法可以使用同样的名字。 在类中访问属性和调用方法使用同样的操作符,具体是访问一个属性还是调用一个方法,取决于你的上下文,即用法是变量访问还是函数调用。
extends
- 一个类可以在声明中用
extends
关键字继承另一个类的方法和属性。PHP 不支持多重继承,一个类只能继承一个基类。 - 被继承的方法和属性可以通过用同样的名字重新声明被覆盖。
::class
关键词 class
也可用于类名的解析。使用 ClassName::class
可以获取包含类 ClassName
的完全限定名称。
签名兼容性规则
实例
转一段王垠关于OOP的论述:
“对象思想”作为数据访问的方式,是有一定好处的。 然而“面向对象”(多了“面向”两个字),就是把这种本来良好的思想东拉西扯,牵强附会,发挥过了头。 很多面向对象语言号称“所有东西都是对象”,把所有函数都放进所谓对象里面,叫做“方法”,把普通的函数叫做“静态方法”。 实际上只有极少需要抽象的时候,需要使用内嵌于对象之内,跟数据紧密结合的“方法”。 其他的时候,你其实只是想表达数据之间的变换操作,这些完全可以用普通的函数表达,而且这样做更加简单和直接。 把所有函数放进对象的做法是本末倒置的,因为函数本身并不属于对象,它们只是对象上面的变换操作。 绝大部分函数是独立于对象的,它们不能被叫做“方法”。 强制把所有函数放进它们本来不属于的对象里面,把它们全都作为“方法”,导致了面向对象代码逻辑过度复杂。 很简单的想法,非得绕好多道弯子才能表达清楚。 很多人至今不知道自己所用的“面向对象语言”里面的很多优点,都是从过程式语言继承来的。