面向对象的三大特性:封装、继承、多态
一个文件只保存一个类,文件名中包含类名,
文件名:类名.class.php
类名:单词的首字母大写
[修饰类的关键字] class 类名 {
成员属性
成员方法
}
(1)成员属性,在类中声明的变量,称为成员属性。声明时,变量前面必须使用一个关键字,如使用public、private、static等关键字修饰,如不需要有特殊意义的修饰,则可使用var
关键字
(2)成员方法,在类中声明的函数,称为成员方法。
类创建后,可以使用 new
运算符来实例化该类的对象。
$变量名 = new 类名称;
成员方法属于哪个对象,$this引用就代表哪个对象。
例:
class Person {
var $name;
function say(){
echo 'my name is '.$this->name;
}
}
$xm = new person; //实例化对象
$xm->name = '小明'; //对象属性的赋值
$xm->say(); //访问对象的成员方法
构造方法的作用是为成员属性初始化
;
构造方法是在对象创建完后,第一个自动调用的方法;
构造方法,方法名固定,在PHP4中构造方法名与类名一致;PHP5中是 __construct()
class Person {
var $name;
var $age;
function __construct($name='', $age=18){
$this->name = $name;
$this->age = $age;
}
function say(){
echo $this->name.$this->age;
}
}
$xm = new person('小明');
$xm->say();
当对象被释放之前最后一个自动调用的方法。
作用:关闭一些资源,做一个清理工作。
名称:__destruct()
C++属于多继承,同一个类可以有多个父类;PHP和Java属于单继承,同一个类只能有一个父类。
声明子类,使用extends
关键字去继承(扩展)一个父类;
子类从父类中继承所有的内容,包括成员属性、成员方法、构造方法…等
class Student extends Person{
var $school;
function study(){
...
}
}
子类可以声明和父类相同的方法名,即子类覆盖了父类中同名的方法
在子类中 调用 父类中 被覆盖的方法
调用方法:父类名::方法名
或 parent::方法名
在子类中编写构造方法,如果父类中也有构造方法一定要去调用一次父类中被覆盖的那个构造方法
注意:子类中重载的方法,不能低于父类中的访问权限
封装的原则就是要求对象意外的部分不能随意存取对象的内部数据(成员属性和成员方法)
和封装私有成员有关的魔术方法:
__set()
:是直接设置私有成员属性值
时,自动调用的方法
__get()
:是直接获取
私有成员属性值时,自动调用的方法
__isset()
:是直接isset
查看对象中私有属性是否存在时,自动调用的方法
__unset()
:是直接unset
删除对象中私有属性时,自动调用的方法
PHP 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。
private(私有):
私有的类成员则只能被其所在的类访问。
protected(受保护):
受保护的类成员则可以被其自身以及其子类和父类访问。(当然,该成员所在的类也可以访问)
public(公有):
公有的类成员可以在任何地方被访问。
类的成员属性
都必须使用关键字public、protected 或 private 进行定义。如果用 var 定义,则被视为公有。
类的成员方法
都必须使用关键字public、protected 或 private 进行定义。如果没有设置这些关键字,则该方法会被设置成默认的 public。
final
1)final不能修饰成员属性
2)final只能修饰类和方法
作用:final修饰的类不能被子类继承,final修饰的方法不能被子类覆盖
static
(静态)1)static可以修饰成员属性和成员方法,不能修饰类;
2)用static修饰的成员属性,可以被同一个类的所有对象共享;
3)静态的数据是存在内存中的数据段中(初始化静态段);
4)静态的数据是在类每次加载时分配到内存中的,以后再用到类时就直接从数据段中获取;
5)静态成员要用类名去访问,不用对象去访问;
类名::静态成员属性名
类名::静态成员方法名()
6)如果在类中使用静态成员,可以使用self
代表本类;
self::静态成员属性名
self::静态成员方法名()
7)静态方法(static修饰的方法),不能访问非静态的成员。
const
(常量)1)只能修饰成员属性;
2)在类中声明常量属性使用const;
3)使用const声明的常量名称前不要使用$
,且常量名称通常都是大写的;
4)访问方式和static静态成员属性一样(在类外部使用 类名::常量
,在类内部使用 self::常量
);
5)常量一定要在声明时就给初值。
instanceof
使用instanceof
可以确定一个对象是否是类的实例、类的子类,还是实现了某个特定接口
$man = new Person();
if ($man instanceof Person) {
echo '$man 是 Person 类的实例对象';
}
__call()
通常在调用对象中不存在的方法时,系统会报错,然后程序退出。
作用:在调用一个对象中不存在的方法时自动调用,处理一些不存在方法的错误调用
__call()
需要两个参数,第一个是调用的不存在方法的方法名,第二个是调用的不存在方法里面的参数
__toString()
直接输出对象引用时自动调用,用来快速获取对象的字符串表示的最便捷的方法。
__clone()
(克隆)__clone()
就是在克隆对象时自动调用的方法,可为克隆出来的对象初始化;
在__clone()
方法中的,$this
关键字,代表的时副本对象,$that
代表原本对象。
$xm = new person('小明');
$xm1 = clone $xm; // 克隆对象时自动调用类中的__clone()方法
__autoload()
(自动加载)注意:其他的魔术方法都是在类中添加,这是唯一一个不在类中添加的魔术方法。
只要在页面中使用到一个类,只要用到类名就会自动将类名作为参数传递给
function __autoload($className){
include './'.$className.'.class.php';
}
__sleep()
在序列化时自动调用的方法
作用:可以将一个对象部分串行化,只要这个方法中返回一个数组,数组中有几个成员属性就序列化几个成员属性,如果不加__sleep()
方法,则所有成员都被序列化。
__wakeup()
在反序列化时自动调用的方法
也是对象重新诞生的一个过程
对象串行化(序列化):将一个对象转化为二进制串(对象是存储在内存中)
serialize()
:参数是一个对象,返回的就是串行化后的二进制串
unserialize()
:参数是对象的二进制串,返回的是新生成的对象。
抽象类是一种特殊的类,接口是一种特殊的抽象类,而多态要使用到抽象类或接口
1)抽象方法
抽象方法,定义:如果一个类中的方法,没有方法体就是抽象方法(就是方法没有使用{}
,而直接使用分号结束)。抽象方法一定要使用abstract
修饰
abstract function test(); //抽象方法
function test(){ } //有方法体,方法体为空,不是抽象方法
2)抽象类
如果一个类中有一个抽象方法,则这个类就是抽象类
抽象类必须使用abstract
修饰
抽象类是一个特殊的类,除了类中有抽象方法,其他的不变(可在抽象类中声明成员属性、常量、非抽象的方法)。
抽象类不能实例化对象(不能通过抽象类去创建一个抽象类的对象)
想要使用抽象类,就必须使用一个子类去继承抽象类,再由这个子类创建对象。(如要使用子类创建对象,子类就必须不能再是抽象类)
抽象类中的抽象方法没有方法体,子类必须实现这个方法(就是定义一些规范,让子类按规范去实现功能)
abstract class Demo{
var $name;
abstract function test(); //抽象方法
function say(){
echo 'hello!';
}
}
class Abc extends Demo{
function test(){
echo '子类继承自抽象类';
}
}
$a = new Abc;
$a->test();
3)接口
抽象类是一种特殊的类,接口又是一种特殊的抽象类。
接口和抽象类是一样的作用
因PHP是单继承的,如果使用抽象类,子类实现完抽象类就不能再去继承其他的类了,如果即想实现一些规范,又想继承一个其他类,就要使用接口。
接口和抽象类对比
1、作用相同,都不能创建对象,都需要子类去创建对象
2、接口的声明和抽象类不一样(使用interface
关键字声明)
3、接口被实现的方式不一样
4、接口中的所有方法必须是抽象方法,只能声明抽象方法(不用使用abstract
修饰)
5、接口的成员属性,只能声明常量,不能声明变量
6、接口的成员访问权限都必须是public
,抽象类中最低的权限protected
7、使用一个类去实现接口,是使用implements
关键字
如果子类是重写父接口中抽象方法,则使用implements
(类–接口,抽象类–接口);而定义另一个接口去继承一个接口之间则使用extends
。
可以使用抽象类去实现接口中的部分方法,如果想让子类可以创建对象,则必须实现接口中的全部抽象方法。
interface Demo{
const HOST = 'localhost';
function fun1();
function fun2();
}
interface Demo2 extends Demo{ //接口Demo2 继承自 Demo
function fun3();
}
class Test implements Demo2{ //子类Test 实现 Demo2 接口 ,必须实现全部的抽象方法
function fun1(){
}
function fun2(){
}
function fun3(){
}
}
abstract class Demo3 implements Demo2{ //抽象类Demo3 实现接口 Demo2 的部分抽象方法
function fun1(){
}
}
class Test2 extends Demo3{
function fun2(){
}
function fun3(){
}
}
一个类可以去实现多个接口(按多个规范去开发子类),使用逗号分隔多个接口名称。
一个类可以继承一个类的同时,去实现一个或多个接口(先继承,再实现)
interface Demo1{
function fun1();
}
interface Demo2{
function fun2();
}
class Person{
}
class Test implements Demo1,Demo2{
function fun1(){
}
function fun2(){
}
}
class Test2 extends Person implements Demo1,Demo2{
function fun1(){
}
function fun2(){
}
}
4)多态性
所谓多态性,是指一段程序能处理多种类型对象的能力;在PHP中多态性指的就是方法的重写,重写要求子类的方法和父类的方法名称相同,这可以通过声明抽象类或接口来规范。