面向对象整理
面向对象知识点整理
面向对象思想介绍
传统的面向过程:将要完成的工作分作若干步骤,或在细分为子步骤,然后按步骤从前往后一步一步完成,然后达到目的,好比做饭,洗菜,切菜,下锅等等每一步都是自己完成最终做成。
现代的面向对象:将要完成的工作拆分为一个一个对象的任务,每个对象独立完成自己的任务,任务之间的连接通过调用来实现,最终也完成了整体的工作。也像做饭只是洗菜,切菜等这些步骤不用自己完成,而是让对象完成,自己最后只负责用就可以。
万事万物皆对象。面向对象是设计思想的升华,面向过程是解决简单问题的自然的思维过程,面向对象是解决大规模的复杂问题的良好思想。
面向对象基本概念
类与对象
张三,李四,王五都是对象,他们都隶属于“人”这个类,同时我们也可以说隶属于 脊椎动物类 同样都是生物类。
类:是用于描述某一些具有共同特征的物体的概念表,是某一类物体的总称。
通常,一个雷所具有的共同特征包括2大方面的信息: 属性;方法。
对象:是指一个具体的物体,该物体隶属于某个类别。
通常,对象离不开类,没有类就不能有对象
原来(在面向过程)的语法中,我们的代码有如下几种代码:
定义变量;
定义函数;
使用变量(输出,赋值,等)
调用函数;
流程控制(if,switch,for,while等)
在面向对象的语法中,则情况就发生变化了:
1,定义类;定义类的语法中,只有这3种代码:
1.1定义属性(变量)
1.2定义方法(函数)
1.3定义常量(类常量)
2,创建类的对象;
$对象名=new 类名();
3,使用对象;
使用其属性:因为属性就是“变量”,则使用其属性,也就是跟以前使用变量一样。
使用其方法:因为方法就是“函数”,则使用其方法,也就是跟以前使用函数一样。
使用其常量:类似使用以前的普通常量。
对象的传值
php中,变量传值方式有2个:
值传递: 传递的时候,拷贝的是数据本身。默认都是值传递。
结果:传递完之后,有了2份同样的数据,但两个变量“相互独立”没有关系。
引用传递: 传递的时候,拷贝的是引用关系。需要使用“&”才能实现引用传递。
结果:传递完之后,数据仍然只有一份,但是两个变量共同指向该数据。
则在面向对象这个层面,基本来说,仍然如此:
默认是值传递:
可以使用引用传递:
有一点不同,值传递复制的是对象标识符
类中成员
一个类的内部可以有3种代码:
属性
方法
类常量
一般属性
定义形式:
形式1: var $v1 ; //定义不赋值
形式2: var $v2 = 2; //定义的同时可以赋值,该值只能是“直接值”,常量(值)
//不能是变量值,也不能是“计算表达式”
形式3: public $v1;
形式4: public $2 = 2; //其实var是“public”一个别名,正式用public更好。
错误形式:
$v1 = 1;
var $v2 = 1+3; //右边不能是计算表达式
public $v3 = $v2; //右边不能是变量
使用形式:
$对象->属性名; //注意:属性名前面没有$符号。
通常,可以出现变量的位置,就可以出现对象的属性
一般方法
方法定义跟原来函数定义几乎一样。
使用是通过类或类的对象来进行的。
$this关键字:$this是一个伪对象,代表当前所属类的当前对象;
类是定义好的某些对象的“模板/模型”
对象是根据该模板/模型所“创建”出来的具体物体
一个对象可以有哪些属性(数据),是由该类来决定的。
一个对象可以做那些事情(方法),也是由该类来决定。
通常认为,一个类(对象),就是拥有一些数据,并通过它自己的方法可以去处理这些数据的“独立体”
系统函数:get_class(对象) 获得某个对象的所属类名,结果是一个类名字符串
静态属性
定义属性的时候,前面加上关键字:static,此时就是静态属性
静态属性有什么用?
对比来说:一般属性,他的值是隶属于该类的具体某个对象(虽然定义在类中),或者说,每个对象的同样的属性的值,有可能不一样。
静态属性就是:只隶属于类本身——也可以看做是所有对象的“共有数据”
静态属性的使用:通过特殊语法,:: 双冒号语法,也叫范围解释符
类::$静态属性名; 普通属性使用 :对象->普通属性名
静态方法
如果在一个方法的前面加上static关键字修饰,则就变成了静态方法。
静态方法同样隶属于类,而不是隶属于具体对象。使用方法跟静态属性类似:
类名::静态方法名();
从理念上,可以认为,静态方法是只隶属于类,而为所有对象所“共有”。
如果通过类名来调用静态方法,则该方法中不可以出现$this关键字。
注意:$this不能在静态方法中使用;静态方法不能调用非静态方法
Self:
含义:代表当前类
使用:通常只能在某个类的某个方法内部代表该类的名称
Class s2{
Public $v1=1;
Static function getNew(){
return new self;//self 代表当前类
new self就是当前类的一个对象
}
}
$obj2=s2::getNew();
Var_dump($obj2);
构造方法
构造方式是类中的一个“特殊”方法,其作用是在实例化一个对象的同时,给该对象的属性赋值,使之一创建完成,就具有了其本身的特有数据
1,该方法名字是固定的,为:_ _construct();
2,该方法必须是普通方法(不能是静态方法)
3,通常该方法应该是public
4,通常该方法中使用$this这个关键字来对属性进行赋值
5,当new 类名()的时候,其实是在调用该构造方法
6,如果一个类中定义了构造方法,则实例化该类时就会调用该方法,且实例化时的参数需要跟构造方法的参数匹配
析构方法
构造方法是“创建”对象的时候会自动调用。
析构方法是“销毁”对象的时候会自动调用。
系统方法通常用于在销毁对象的时候来“清理数据”(打扫战场)——如果需要,就可以利用这个机会去处理。
通常,php程序结束后,所有对象都会自动销毁(其实属于php内部的垃圾回收机制)
1,析构方法通常不太需要去定义。
2,析构方法不能调用。
3,析构方法不能有形参。
4,析构方法中可以用于清理一些在php代码结束后不能清理的数据,如生成的文件。
对象销毁的几个情形:
1、 脚本程序运行结束,自动销毁
2、 明确的unset()一个对象变量,则被销毁
3、 改变对象变量的值,被销毁
实际上,更本质来说,当一个对象(new 出来的对象)没有任何一个变量指向它的时候,该对象就会被自动销毁——自然,如果整个程序结束,也会销毁。
类的继承
子类继承父类的所有特征,并且子类还有自己的特有特征;
基本概念
继承:一个类从另一个已有的类获得其特性成为继承
派生:从一个已有的类产生一个新的类,称为派生
已有类称为父类,新建类为子类
单继承:一个类只能从一个上级类继承其特性信息。
扩展:在子类中再来定义自己的一些新的特有的属性,方法。常量。没有扩展继承也就没有意义了
访问修饰符
在类中的成员,通常都可以在前面加上以下3个修饰符:
Public:公共
Protected:受保护的
Private:私有的
public公有的
用该修饰符修饰的成员,可以在“任何位置”使用(访问)。
访问(使用)是这样一个语法模式:
对象->成员;
类名::成员;
访问位置分为3个:
1:某个类内部:自然是该类的某个方法中
2:某个类的具有继承关系的子(父)类的内部:是指其他类的某个方法中。
3,某个类的外部:一般就是独立的代码区(不在类中),类似我们之前的代码。
protected 受保护的
protected修饰的成员,可以在当前类或当前类的上下级具有继承关系的类中访问。
private私有的
private 修饰的成员,只能在其所在的类中访问。
parent代表父类
对比self代表当前类,parent通常用于在子类中调用父类的成员的时候使用,多数就是使用父类的静态类成员
class C{
public $p1 = 1;
function showMe(){
echo "<br />我是父类,数据有:";
echo "<br />C中p1=" . $this->p1;
}
function __construct($p1){
$this->p1 = $p1;
}
}
class D extends C{
public $p2 = 2;
function __construct($p1,$p2){
//经典用法
parent::__construct($p1);//调用父类的构造函数来初始化p1
$this->p2 = $p2; //初始化p2
}
function showMe2(){
echo "<br />我是子类,数据有:";
//基本用法:
parent::showMe();//调用父类的showMe方法,
echo "<br />D中p2=" . $this->p2;
}
}
$d1 = new D(10,20); //此时就需要尊照构造函数的参数结构来使用
$d1->showMe2();
构造方法析构方法在继承中的表现
子类中没有定义构造方法时,会自动调用父类的构造方法。因此实例化子类时,需按照父类的构造方法的形式进行。
子类定义了自己的构造方法,则不会自动调用父类的构造方法,但可以手动调用:parent::__construct();
通常,在子类,很多时候,在构造方法中,都应该去调用父类的构造方法减少代码,增加可读性
Class c{
Public $p1=1;
Public $p3=3;
Function __construct($p1,$p3){
$this->p1=$p1;
$this->p3=$p3;
}
}
Class d extends c{
Public $p2=2;
Function __construct($p1,$p2,$p3){
Parent::__construct($p1,$p3);
$this->p2=$p2;
}
Function show(){
Echo “<br>p1=$this->p1”;
Echo “<br>p2=$this->p2”;
Echo “<br>p3=$this->p3”;
}
}
$d1=new d(10,20,40);
$d1->show();
子类中没有定义析构方法时,会自动调用父类的析构方法。
子类定义了自己的析构方法,则不会自动调用父类的析构方法,但可以手动调用:parent::__destruct()
重写override
重写又叫覆盖,就是将从父类继承下来的属性或方法重新“定义”——就是从新写。
注意:重写需要子类跟父类的方法同名同参,构造方法可以不同参
私有属性和私有方法的重写问题:私有属性和方法都不能覆盖,但其实子类可以定义跟父类私有的同名属性或方法。只是当作一个自身的新的属性或方法来看待而已。不过方法的参数必须一致。
最终类final class:
通常,一个类,没有特别声明的话,则“别人”就可以随意拿过来使用并对之进行“扩展”——继承。
但是:
如果某个类不希望对其进行扩展,则可以将其声明为“最终类”。
形式:
final class 类名{ 。。。。类定义。。。。}
最终方法final method
通常,一个方法,如果没有特别声明,则下级类就可以对其进行“覆盖”(重写)。
但是:
如果某个方法不希望被下级类覆盖,就可以对其生命为“最终方法”。
形式:
final function 方法名(){。。。。方法定义。。。。}
设计模式
什么叫设计模式
所谓设计模式,就是一些解决问题的“常规做法”,是一种认为较好的经验总结。面对不同的问题,可能会有不同的解决办法,此时就可以称为不同的设计模式。
工厂模式
在实际应用中,我们总是需要去实例化很多很多的类——以得到对象。
则:
我们可以设计出一个“工厂”(其实就是类),该工厂的作用(任务)就是为人们“生产”各种对象。这种工厂通常只要指定类名,就可以据此获取一个该类的对象。
单例模式
对于某些类,在使用它的时候,从头到尾(程序运行的开始到结束),都只需要一个对象,就可以完成所有任务。
某个类,只允许其“创建”出一个对象,即使去进行多次创建,也只能得到一个对象。
注意:1、属性私有化
2、构造私有化
3、方法私有化
4、克隆私有化
抽象类,抽象方法
抽象类
在正常定义类的前面加上关键字:abstract,就构成抽象类
abstract class 类名{.....类的定义.....}
抽象类用来规范一些类的共同特性,但不需要对其实例化,专门作为父类
抽象方法:
抽象方法是一个没有方法体(也不含大括号)的方法定义“头”而已。
前面需要加上abstract。
比如:abstract function f1($x1, $y, $m) ;
跟抽象类一样,配合抽象类,来实现对下级类的“行为规范”。
即相当于要求下级类去完成该功能(动作),但自己是不做的。
抽象类抽象方法细节关系描述
1,如果一个方法定义为抽象方法,则其所在的类必须定义为抽象类。
2,但,一个抽象类中,可以没有抽象方法——但通常意义不大。
3,子类继承自一个抽象类,则子类必须实现父类中的所有抽象方法,除非子类也继续作为抽象类
4,子类实现抽象父类的方法时,访问控制修饰符的范围不能降低,且方法的参数也须一致——其实这就是重写,所以要满足重写的要求。
Php中的重载技术
属性重载: 如果使用一个不存在的属性,就会去自动调用类中预先定义好的某个方法以处理数据;
方法重载: 如果使用一个不存在的方法,就会去自动调用类中预先定义好的某个方法以处理该行为
属性重载
属性有哪些使用情形?其实跟变量一样,只有4种使用情形:
取值:$v1 = 对象->属性;
赋值:对象->属性 = XX值;
判断是否存在:isset(对象->属性;)
销毁:unset(对象->属性;)
所谓属性重载,就是在面对上述4种情形的属性使用场景中,该对象如果来“应对”的问题。
如果某属性不存在,但在语法中使用如下情形,则会发生:
取值:$v1 = 对象->属性; ===>自动调用类中的__get()方法
赋值:对象->属性 = XX值; ===>自动调用类中的__set()方法
判断是否存在:isset(对象->属性;) ===>自动调用类中的__isset()方法
销毁:unset(对象->属性;) ===>自动调用类中的__unset()方法
前提都是:类中要预先定义好这些方法。
方法重载
当使用一个对象调用一个不存在的普通方法的时候,会自动去调用预先定义好的"__call"方法。
其中,该方法必须带2个参数
当使用一个对象(类)调用一个不存在的静态方法的时候,会自动去调用预先定义好的"__callStatic"方法。
其中,该方法必须带2个参数。其实跟前面一样!
魔术方法:__get(), __set(), __isset(), __unset(), __call(), __callstatic();