文章目录
- 面向对象概念
- 关键字说明
- 关于类
- 类成员
- 访问修饰限定符
- 类内部对象-this对象
- 开发规范
- 构造方法
- 析构方法
- 对象传值
- 范围解析操作符(类常量访问)
- 静态成员
- self关键字
- 对象克隆
- 面向对象高级
- 封装
- 继承
- 多态
面向对象概念
面向对象编程也叫做OOP编程(Objected Oriented Programming),是一种基于面向过程的开发思想。与面向过程强调分解事务步骤相似,面向对象更需要追求事务操作的“主体”,也就是对象
- 面向对象编程是一种编程思想,不是一种具体技术
- 面向对象是在面向过程基础之上发展而来,因此也是一种模块化编程思想(有函数)
- 面向对象能够更加方便的实现代码的重复利用(适用于大型项目)
- 在面向对象思维中,任何动作的执行或者数据都属于对象(一切皆对象)
总结
- 面向对象编程是一种编程思想,与技术无关
- 面向对象编程的本质是增加数据和功能的操作主体,即对象
- 面向对象中所有的数据和功能都是由主体(对象)来调用和操作
关键字说明
1.类:class,是定义面向对象主体的最外层结构,用来包裹主体的数据和功能(函数)
2.对象:object,也被称之为实例(instance),是事务的具体代表,也是实际数据和功能操作的具体单元
3.实例化:new,从一个抽象的概念(类)得到一个符合抽象概念的具体实例(对象)的过程
4.类成员:member,指类class结构中的所有内容,类成员里有三种
- 方法:method,本质是在类class结构中创建的函数,也称之为
成员方法
或者成员函数 - 属性:property,本质是在类class结构中创建的变量,也称之为
成员变量
- 类常量:constant,本质是在类class结构中创建的常量
关于类
1.定义类基本语法:class 类名{}
,类class是一种结构,如果写好没有语法错误的情况下,代码不会自动执行(与函数定义一样),也无法打印输出
class Nothing{} //空类
var_dump(Nothing); //错误,提示未定义的常量
2.类的命名规范:类的命名规范与函数类似,区别在于人为的通常会将类名的首字母大写,如果碰到多单词组成的类名,通常使用驼峰法
3.类无法直接访问,需要得到类的具体对象才能访问,可以通过实例化new来实现对象的创建:new 类名[()]
4.对象创建后可以直接使用或者打印,但是为了方便后续使用,通常使用变量保存实例化的对象
var_dump(new My);
$m = new My;
var_dump($m); //输出:object(My)#1 (0) { } object(My)#2 (0) { }
打印分析:
object:对象 (My):类名 #1:编号 (0):成员变量(属性)个数 {}:具体成员变量信息(键值对)
类成员
类成员,指直接定义在类结构{}内部的一级成员,即直接依赖{}的成员。在PHP中类成员有三种:成员变量(属性),成员方法(成员函数)和类常量
类成员中:属性、类常量和方法都可以无限定义,但是定义的原则是相关性。除了以上三个类成员,不能在类结构{}中直接写其他任何代码
<?php
class Buyer{
echo __CLASS__; //错误
define('PI',3.14); //错误
if(true){ echo 'hello world'} //错误
}
关于成员变量
1.成员变量:就是在类结构{}下直接定义的变量,但是定义的方式与普通变量稍微有点不同,需要在变量名字前使用一个访问控制符修饰
- 定义语法:
访问控制符 变量名字 [= 值]
成员变量可以赋值也可以不赋值。
class Buyer{
//$name; //错误
public $name; //正确:没有赋值
public $money = 0; //正确:有赋值
}
2.成员变量的访问:成员变量必须通过对象才能进行访问,也就是需要先通过实例化得到对象,然后通过对象实现对成员变量的增删改查
- 访问/修改/删除/新增属性语法:
$对象名->属性名;
- 注意属性名不需要带$符号
$b = new Buyer();
//访问属性
echo $b->money;
//修改属性
$b->money = 1000;
//删除属性
unset($b->name);
//新增属性
$b->age = 20;
注意:删除属性和新增属性通常使用较少,更多的属性操作是访问和修改
关于成员方法
成员方法:在类当中定义的函数
成员方法访问:成员方法也是需要通过对象进行访问的
- 访问语法为:
$对象名->方法名字();
class Buyer{
//定义方法
public function display(){
echo __CLASS__; #输出类名
}
}
$b = new Buyer();
$b->display();
关于类常量
类常量是在类结构{}下定义的常量,类常量的定义只能使用一种方式:const 常量名 = 值;
注意:类常量不是由对象来进行访问,而是通过类域来访问
class Buyer{
//定义类常量
const PI = 3.14;
}
echo Buyer::PI;//3.14
访问修饰限定符
关于类内部和类外部
-
类内部:是指类定义的内容内部,即类名后{}内部
-
类外部:是指类定义的外部内容,即类名后{}之外的所有地方
类成员的访问权限控制是内部访问(私有)、链内部访问(受保护)和全部访问(公有)
在PHP中访问修饰限定符分为三种:public、protected和private
1.public:公有,即表示所修饰的内容(属性或者方法)可以在当前类的内部访问,也可以在类的外部访问
2.protected:受保护,即表示所修饰的内容只能在类的内部访问,外部不能访问
3.private:私有,即表示所修饰的内容只能在当前类的内部访问
4.访问修饰限定符不只是限定属性,也用来限定方法
属性(成员变量)必须写清楚访问修饰限定符,方法可以省去(不建议),因为方法的访问限定符默认是public
<?php
class Saler{
//属性
public $count = 100;
protected $discount = 0.8;
private $money = 100;
public function getCount(){}
protected function getDiscount(){}
private function getMoney(){}
function getAll(){} #如果没有指定访问修饰限定符,默认public
}
类内部对象-this对象
$this代表的是当前对象,$this所在环境为类内部的方法内部,所以$this对象是在类内部访问,因此可以访问所有的属性和方法,不受访问修饰限定符限制
关于class,new,$this的关系
- class是定义类结构,属于非执行段代码,因此会被加载到代码段(编译阶段)
- new是实例化对象,先判定类在内存(代码段)是否存在
- 类不存在,报错
- 类存在,将类内部的属性部分复制一份,然后在内存(堆区)开辟一块内存空间,将属性放到里面,同时内部有一个指针指向类的内存空间(代码段)
对象访问属性即访问的是对象空间里存储的部分,对象访问方法是对象通过内部指针找到类空间中的方法,然后在内存(栈区)开辟运行
- $this是系统在方法内置的对象通用名字
- 对象在调用方法的时候,系统会自动找到对象所保存的内存地址(堆区),然后把地址赋值给$this
- $this的本质是函数内部的一个局部变量,代表的是调用方法的对象本身
开发规范
属性的初始化:
属性在类中定义的时候,通常不会初始化值,除非所有类实例化得到的对象的某个属性需要是统一值
属性在类中初始化的基本判定就是数据是否初始化的时候统一
访问修饰限定符选择:
- 设定好的类成员本身不会被外部用到,那么应该使用private或者protected
- 设定好的类成员一定会给外部访问,使用public
- 属性通常private居多,如果需要外部访问属性,通常会定义相关方法来实现属性的查看和修改,因为可以在方法内对数据逻辑进行代码控制,安全
- 总之一句话:尽可能增加类对成员的控制(尽可能多使用private,少使用public)
<?php
class Saler{
//属性
public $count;
private $money = 0;
//增加方法操作私有属性money
public function getMoney(){
return $this->money;
}
public function setMoney($money){
//可以对逻辑进行修改,对数据进行安全判定,保证数据的安全性
$this->money = $money;
//$this->money是属性,$money是外部传入的参数,二者同名但是性质完全不同
}
}
构造方法
构造方法__construct(),是一种类结构特有的特殊方法,在实例化对象的时候,对象就会自动调用构造方法。
说明:
1.构造方法也是一个普通方法,不普通的地方在于,类实例化得到的对象会马上自动调用
2.构造方法的意义:构造方法是对象实例化的时候用来初始化对象的资源的,所以通常是用来初始化对象的属性或者其他资源初始化
3.一旦构造方法拥有了形参,那么对象在调用该方法的时候就需要传入对应的实参,而构造方法又是自动调用的,所以需要在实例化对象的时候使用new 类名(构造方法对应的实参列表)来实现
- 注意:之前的
new 类名
和new 类名()
没有区别是因为没有构造方法,或者构造方法没有参数限定,一旦构造方法有了参数,那么new 类名
就不能直接使用了。
4…我们也可以手动调用构造方法(但是一般没有价值,因为对象实例化时会自动调用)
<?php
class Saler{
//属性
public $count;
private $money;
//构造方法:初始化属性
public function __construct($count,$money){
$this->count = $count;
$this->money = $money;
}
}
//实例化
$s = new Saler(100,100); //系统在new Saler(100,100)好之后,会自动调用一次
$s->__construct(1000,1000); //允许手动调用
析构方法
析构方法__destruct()
,也是一种类结构中特殊的方法,析构方法是在对象被销毁时自动调用
说明
1.析构方法是对象用来调用释放对象中的资源,不是用来删除对象的
2.析构方法也是普通方法,可以由对象直接调用
3.PHP中脚本执行结束,系统会自动回收所有资源,因此一般PHP中很少使用析构方法
对象传值
在PHP中,对象的传值是引用传递的:即一个对象变量赋值给另外一个变量,两个变量指向同一个对象的内存地址,即只有一个对象。所以不管对象赋值给多少个变量,内存中只有一个对象
<?php
class Saler{}
$s1 = new Saler();
$s2 = $s1;
//证明
var_dump($s1,$s2); //同一个对象
$s1->name = 'Saler'; //更改一个变量所保存对象的属性
echo $s2->name; //输出Saler
范围解析操作符(类常量访问)
范围解析操作符,由两个冒号组成::
,是专门用于类实现类成员操作的,可以实现类直接访问类成员。
对象无法访问类常量,那是因为类常量的定义本身就是用来给类访问的,对象是用来访问属性和方法的,类常量的访问方式为:类名::常量名
<?php
class Saler{
//类常量
const PI = 3.14;
}
echo Saler::PI; //输出3.14
静态成员
使用static关键字修饰的类成员,表示该成员属于类访问。PHP静态成员有两种,静态属性和静态方法。
静态属性
静态属性:在类中定义属性的时候使用static关键字修饰,访问的时候只能使用类+范围解析操作符+静态属性访问
<?php
class Saler{
//属性
public $money = 0;
public static $count = 0; //静态属性
}
//静态成员可以直接使用类访问,而不需要先实例化对象
echo Saler::$count;
在类的内部也可以访问静态成员,同样是使用类名+范围解析操作符+静态属性/静态方法()
静态方法
在类中定义方法的时候使用static关键字修饰,访问的时候使用类+范围解析操作符+静态方法名字()访问
- 在类的内部也可以访问静态成员,同样是使用类名+范围解析操作符+静态属性/静态方法()
- 静态方法本质也是类中定义的方法,因此也可以使用对象进行访问,但是不建议
- 静态方法本质是给类访问,所以不允许在静态方法内部使用$this对象
<?php
class Saler{
//属性
private static $count = 0; //私有,不允许外部直接访问
//方法
public static function showClass(){
echo Saler::$count;
}
}
//类直接访问
Saler::showClass();
//对象访问静态方法
$s = new Saler();
$s->showClass(); //输出0
静态成员的访问效率比非静态成员高,因此有种说法是能用静态的时候就不用非静态
self关键字
self关键字是一种在类内代替类名的写法。能够保障用户方便修改类名字。
1.self是用来代替类名的,与范围解析操作符::
一起使用的
class Saler{
private static $count = 0; //私有,不允许外部直接访问
public static function showClass(){
echo Saler::$count;
echo self::$count; //代替类名self ==> Saler
}
}
2.self也可以在类的内部方便实例化对象:比如构造方法被私有化之后,就没有办法在类外部实例化对象,此时可以在类内部进行对象实例化 (单例模式)
<?php
class Saler{
private static $count = 0; //私有,不允许外部直接访问
private function __construct(){} //私有,不允许外部实例化(因为对象不能外部调用)
public static function getInstance(){
//return new Saler(); //使用类名实例化
return new self(); //使用self关键字实例化
}
}
$s = Saler::getInstance();
3.self可以用来在类内部访问静态成员 / 类常量
对象克隆
上述我们已经得知:对象的传值是引用传递的,所以不管对象赋值给多少个变量,内存中只有一个对象。
- 克隆对象
clone
,即通过已有的对象复制一个新的同样的对象,但是两者之间并非同一个对象。
1.对象克隆是通过clone关键字实现,即:clone 对象。克隆出来的对象与原来对象是两个内存地址,因此是两个不同的对象
2.对象在实例化的时候会自动调用存在的构造方法__construct()
,同样的,在类的内部,PHP允许定义一个__clone()
的方法,在对象被克隆后,新克隆出来的对象会自动调用
<?php
class Saler{
//属性
public $count;
private $money;
//克隆方法
public function __clone(){
var_dump($this);
$this->count++;
}
}
//实例化
$s1 = new Saler();
$s1->count = 1;
//克隆
$s2 = clone $s1;
?>
3.如果不允许对象被克隆,可以将__clone()
方法私有化(本质是不允许对象在外部被克隆)
面向对象高级
面向对象的三大特性:封装,继承,多态
封装
封装,字面意思就是将内容装到某个容器中,并进行密封保存。在面向对象思想中,封装指将数据和对数据的操作捆绑到一起,形成对外界的隐蔽,同时对外提供可以操作的接口。
- 数据:即要操作的数据,在面向对象的具体体现就是类成员属性(属性和静态属性)和类常量,这些都是在类的内部定义的用来保存数据的
- 捆绑到一起:即使用类结构{}将属性、类常量和方法存放到一起,成为一个整体
- 对外提供可操作的接口:即提供可以供外部访问的类成员(通常是方法)
//封装特性
class Saler{ //捆绑内容到一起,形成对外界隐蔽的整体
const ALLOW = true;
private static $count = 0;
private $money = 0; //数据:属性和类常量保存
public function getMoney(){ //数据操作
return $this->money;
}
}
//外部
$s = new Saler();
$s->getMoney(); //外部只能访问类中公有的方法,具体实现不可见
继承
0.继承extends是面向对象思想中实现代码在类级别重复利用的重要特性
1.继承的基础:子类(要继承其他类的类,也称之为派生类)与父类(被继承类,也称之为基类)之间本身是一种包含于被包含关系(is - a
),如此才有可继承的前提
2.继承关键字:extends
,子类想要继承父类,则必须在子类结构声明时明确使用extends关键字来继承相关类
3.继承效果:子类可以不用自己去实现某些功能,而可以直接访问父类中已经存在的成员,继承是指子类可以直接访问父类中已经存在的成员
//父类
class Human{
public function eat(){
echo '吃饭';
}
}
//子类
class Man extends Human{} //子类为空类:没有类成员
//实例化子类对象
$m = new Man();
$m->eat(); //输出吃饭
4.继承可以节省代码工作,同时允许子类中进行扩展,即在子类中增加必要的父类不存在的功能
多态
1.多态:是指在发生类的继承的情况下,同时出现方法的重写(override),即子类拥有与父类同名的方法。然后在实例化对象的时候让父类对象指向子类对象(强制类型,PHP不支持),父类对象表现的子类对象的特点。
2.PHP是弱类型语言,所以不存在变量的强制类型,因此PHP不支持多态。