php 面向对象笔记
PHP的面向对象:
对象是客观存在的一个实体。
类是对对象抽象的一个描述。
概念:对象(实体)、类、 类与对象的关系。
oop面向对象编程的特点:封装、继承、多态
类和对象的关系:
类的实例化结果就是一个对象(使用new关键字)
对对象的抽象描述就是一个类
===================================================
一、如何定义一个类,和使用
1.1 语法格式:
[修饰符] class 类名 [extends 父类] [implements 接口1[,接口2...]]{
【成员属性】定义变量
【成员方法】定义函数
}
1.2 成员属性格式:
修饰符 $变量名[=默认值]; 如:public $name="zhangsan";
注意:成员属性不可以是带运算符的表达式、变量、方法或函数的调用。 如:
public $var3 = 1+2;
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
正确定义方式:
public $var6 = 100; //普通数值(4个标量:整数、浮点数、布尔、字串)
public $var6 = myConstant; //常量
public $var7 = self::classConstant; //静态属性
public $var8 = array(true, false); //数组
常用的属性修饰符:public、protected、private、static、var
1.3 成员方法格式:
[修饰符] function 方法名(参数..){
[方法体]
[return 返回值]
}
常用的方法修饰符:public、protected、private、static、abstract、final
1.4 对象:类的实例化就会产生一个对象。
如: $p = new Person();
1.5 $this 关键字: 表示自己,表示当前使用对象,*哪个对象调用代表哪个
1.我们在类中调用自己的成员属性或方法都是使用 $this->调用。
2.注意:静态方法不可以使用$this关键字
===================================================
二、构造方法和析构方法
2.1. 构造方法:
1.当我们通过new关键字来创建一个对象时,第一个自动执行的方法称为构造方法。
2.方法名__construct(); 主要用于初始化对象。
(在php4.0时可使用与类名重名的方法作为构造方法)
2.2. 析构方法:当这个对象被销毁时最后自动调用的方法,称为析构方法。
1.__destruct(); 目的是释放资源(如关闭连接、文件,释放资源)
2.对象被销毁时最后自动调用
===================================================
三、封装(访问控制)
3.1 封装:就是将"属性" private或protected 私有,并提供公有的setter放置与getter取值方法
public(公有) protected(受保护) private(私有)
===========================================================
在本类中 Y Y Y
在家族中 Y Y N
在类外边 Y N N
public 类外需要调用此类内的方法或属性时使用
protected 类外不需要调用,而家族内需要使用
private 用于安全信息,只用于当前类
===================================================
四、 重载
4.1 属性重载中的四个魔术方法:__set() __get() __isset() __unset()
__get():当我们直接输出一个对象中的非公有属性时会自动调用的方法,
并将属性名以第一个参数传进去。
__get($name){...} //外部:$m->priAge;
__set():当我们直接设置一个对象中的非公有属性时会自动调用的方法,
并将属性名以第一个参数,值作为第二参数传进去。
__set($name,$value){...} //外部:$m->priAge = 100;
__isset():验证一个对象属性isset($this->name) 或 empty($this->name)时, $this->name是一个非公有属性时,自动调用此方法。
public function __isset($param){
return isset($this->$param);
}
__unset()当销毁一个对象属性unset($this->name), $this->name是一个非公有属性时,自动调用此方法。
public function __unset($param){
unset($this->$param);
}
4.2 方法的重载:
mixed __call ( string $name , array $arguments )
mixed __callStatic ( string $name , array $arguments ) php5.3.0支持
1.当调用一个不可访问方法(如未定义,或者不可见)时,__call() 会被调用。
2.当在静态方法中调用一个不可访问方法(如未定义,或者不可见)时,__callStatic() 会被调用。
第一个参数表示方法名,第二参数表示调用时的参数列表(数组类型)
class A {
//调用不存在的方法
public function __call($methodName,$args) {
echo $methodName;
print_r($args);
}
//调用不存在的静态方法
static public function __callStatic($methodName,$args) {
echo '
'.$methodName;
print_r($args);
}
}
$a = new A;
$a->say('a','b');
A::test('c','d');
===================================================
五、 继承
5.1 继承:extends
*继承的目的:为了减少重复的代码。
假如B类继承A类,那么就继承了A中所有非私有属性和方法.其中A叫父类(基类)B叫子类(派生类)。
class B extends A{
....
}
1.*parent:若子类出现覆盖父类的方法,那么想调用被覆盖掉的父类方法,并可以跟子类的方法融合为一起
格式:parent::父类方法 | 父类名称::父类方法
class A{
public function __construct(){
//....
}
}
class B extends A{
public function __construct(){
parent::__construct();//注意要调用一下父类的构造方法
//....
}
}
2.继承的特性
1、PHP支持单继承,一类只能继承一个父类
2、PHP支持多层继承,可以有子孙类
3、子类会继承父类所有属性和方法,但是私有的属性和方法不能调用
3.属性的继承
1、私有的属性不会被覆盖,其他会被覆盖。
2、属性的修饰只能更加松散,不能更加严谨。 松散性:public > protected > private
3、如果子类中有与父类同名的属性,父类有public $name 子类只能使用public修饰
3、如果子类中有与父类同名的属性,父类有protected $name 子类能使用protected,public修饰
4.方法的继承
1、所有方法可以被继承,但是私有的方法不能被使用
2、如果子类有与父类同名的方法,那么除了私有的方法,其他都被覆盖掉。
3、如果子类有与父类同名的方法,方法的修饰只能更加松散,不能更严谨。
===================================================
六、 final、static和const
*内存逻辑上:常量区(常量、静态属性)、代码区(类、函数)、栈内存(普通的小的变量)、堆内存(大的变量)
6.1 final关键字:主要用于修饰类与成员方法
目的:一是为了安全,二是没有必要
1.使用final关键字修饰类,表示这个类不能被继承,防止有子类的覆盖
2.使用final关键字修饰的方法,不可以在子类中被覆盖(重写)。
3.使用final关键字不能修饰属性
final class B {
final public function A {
..
}
}
---------------------------------------------------------------
6.2 static关键字:表示静态的意思,用于修饰类的属性和方法
static关键字修饰 属性/方法 称为 静态属性/静态方法,
注意:静态方法在实例化后的对象不可以访问 //$对象名->静态方法名
1.可以不用new(实例化)就可以直接使用方法或属性
*外部调用:类名::方法名 | 类名::属性名
*类中调用:self::静态属性名 | self::静态方法名
*2.静态属性是共享的。也就是调用多个对象也是指向同一个地址
3.在静态方法中不可以使用非静态的内容。就是不让使用$this
4.在一个类的方法中若没有出现$this的调用,默认此方法为静态方法。
5.static不能修饰类
---------------------------------------------------------------
6.21 设计模式。目的:节省资源
1、单例设计模式 2、工厂设计模式 3、 抽象工厂设计模式
class Single
{
//定义一个静态属性,用来存放对象
static private $obj = null;
//私有化构造方法。不能在类的外部实例化对象
private function __construct() {}
//实例化对象
static public function test() {
//如果没有对象,我们就允许它new一个对象
if(!self::$obj) {
self::$obj = new Single();//创建对象
}
//有了对象,就直接返回之前的对象
return self::$obj;
}
//单例不允许克隆
public function __clone() {
trigger_error('错误', E_USER_ERROR);
}
}
$s1 = Single::test(); var_dump($s1);
$s2 = Single::test(); var_dump($s2); //调用同一个对象
$s3 = clone $s2; //报错
---------------------------------------------------------------
6.3. const关键字: 在类中修饰成员属性,将其定义成常量(不可修改的),
1.一般要求常量名都是大写的,没有“$”符 没有其他修饰符(public)
2.定义格式:const 成员常量名="值";
3.使用:
*外部调用:类名::成员常量名;
*类中调用:self::成员常量名;
---------------------------------------------------------------
6.4. 检测当前对象是属于谁的类(家族类也是)
1.instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例:
class A {}
class B extends A {}
$b = new B;
if($b instanceof A) {echo 'y';}
2.is_a — 如果对象属于该类或该类是此对象的父类则返回 TRUE
===================================================
七、 类型约束
1. 类型约束可以使用的类型是:数组,对象,回调函数。
若指定的一个类名,那么可传入本类及子类的对象进去。
可以使用的约束类型:(复合类型)数组array,类名、抽象类名、接口名
class MyClass
{
//第一个参数必须为类OtherClass的一个对象
public function test(OtherClass $otherclass) {
**可以传入别的类,调用别的类的方法和属性
echo $otherclass->var;
//同这里
if( $otherclass instanceof Hanzi){
$otherclass->qinqin();
}
}
//第一个参数必须为数组
public function test_array(array $input_array) {
print_r($input_array);
}
}
===================================================
八、其他魔术方法:
1. 对象复制clone 克隆一个对象,因为对象属于引用类型,普通的“=”号属于引用赋值,
所有需要clone来复制一份。
魔术方法:__clone() 当执行clone克隆时会自动调用的方法。
class A {
public function __clone() {
//自动执行
}
}
$a = new A;
$b = clone $a; //克隆,是两个对象
-----------------------------------------------------------------
2. __toString()方法:魔术方法,当我们直接要输出一个对象时,如echo $a,print $a,
那么会自动调用的方法。
注意:__toString()方法必须返回一个字串类型的值。
class A {
public function __toString() {
return '这是一个对象,不允许ehco,print...';
}
}
$a = new A;
echo $a; //报错
-----------------------------------------------------------------
3. *自动加载"类函数"__autoload(类名):
当new 实例化一个对象时,这个类若不存在,则自动调用此函数,并将类名存入参数
我可以使用这个实现类的自动加载。
function __autoload($className) {
include './autoload/'.$className.'.class.php';
}
$a = new A;
$a->say(); //say
//在 autoload/A.class.php下
class A{
public function say() {
echo 'say';
}
}
-----------------------------------------------------------------
4. __invoke把对象当成函数使用的时候自动调用
class A {
public function __invoke() {
echo 'aa';
}
}
$a = new A;
$a(); //aa
===================================================
九、 对象序列化(串行化)(webservice XML)(在对象持久化存储、和传输中使用)
serialize() -- 序列化
unserialize() -- 反序列化
1.php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。
2.unserialize()函数能够重新把字符串变回php原来的值。
3.序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。
1.__sleep(): 是执行串行化时自动调用的方法,目的是实现资源类型的属性的关闭操作。
@@sleep方法需要返回一个数组,其中数组中的值是序列化时要保留的属性名
2.__wakeup():是在执行反串行化时自动调用的方法,目的是实现资源属性的打开(sleep方法关闭的资源)
//实例:
class A {
public $name1 = 'xiaohei';
public $name2 = 'xiaobai';
public function demo() {
return 'aa';
}
//序列化自动调用的方法
public function __sleep() {
return array('name2'); //只想存储name2,就返回name2
}
//反序列化自动调用的方法
public function __wakeup() {
echo '###';
}
}
$a = new A;
//序列化
$data = serialize($a);
//存入文件
file_put_contents('./1.txt', $data);
//获得数据
$str = file_get_contents('./1.txt');
echo $str; //O:1:"A":1:{s:4:"name";s:7:"xiaohei";}
//反序列化
$tmp = unserialize($str);
print_r($tmp); //A Object ( [name] => xiaohei )
-------------------------------------------------------------------------------------
JSON格式的字符串进行编码/解码
json_encode:对变量进行 JSON 编码
json_decode:对 JSON 格式的字符串进行编码
$arr = array('id'=>1, 'name'=>'jack');
$str1 = json_encode($arr);
echo $str1; //{"id":1,"name":"jack"}
$a = json_decode($str1, true); //加true返回array,否则返回object
echo $a; //Array ( [id] => 1 [name] => jack )
===================================================
十、 抽象类:
目的:抽象类对于子类(实现类),有一个约束的作用,
特点:
//1.定义抽象类
abstract class A {
//2.定义抽象方法
abstract public function test1();
abstract public function test2();
//3.可以有普通方法和属性,不需要子级实现
public function demo() {}
public $name = 'aa';
//4.不能定义抽象属性 Fatal error
abstract public $age = 18;
}
class B extends A {
//5.@@继承了抽象类的"普通类"必须实现抽象类的"所有抽象方法"
public function test1() {}
public function test2() {}
//6.包含了抽象方法的类必须是抽象类,Fatal error
abstract function test3() {}
}
abstract class C extends A {
//7.不能覆盖抽象方法,Fatal error
abstract public function test1() {}
//8.可以继承抽象类的同时添加抽象方法
abstract public function test3();
}
//8.不能实例化,Fatal error
$c = new C;
===================================================
十一、 接口:
目的:同抽象类相同,是更具体的抽象类
假如一个抽象类中所有的方法都是抽象的,那么我们可以使用另外一种方式定义:接口
接口使用关键字interface来定义,接口中只能有常量与抽象方法。
//1.定义接口
interface A {
//2.接口不能有普通属性,Fatal error
public $name = 'aa';
//3.接口不能有普通方法,Fatal error
public function test() {}
//3.但可以定义常量
const HOST = 'aa';
//4.定义接口方法,不需要abstract
public function test1();
}
interface B {
//5.接口之间是继承关系,重复定义Fatal error
const HOST = 'bb';
public function test2();
}
class C {}
//6.可以同时继承"单"类、实现"多"接口(先继承,后实现)
class D extends C implements A,B {
//7.@@继承了抽象类的"普通类"必须实现抽象类的"所有抽象方法"
public function test1() {}
public function test2() {}
}
抽象类和接口总结:
1.目的:制定规范,为了限制其子类
2.选择:如果规范中需要有"普通方法"就选择抽象类
3.区别:
1.定义关键字不同。抽象类:abstract 接口:interface
2.继承/实现关键字不同。抽象类:extends 接口:implements
3.抽象类可以有普通方法,接口不能有普通方法
4.抽象类只能被单继承,接口可以多实现
5.接口不能有成员属性,只有常量与抽象方法
===================================================
十二、多态
定义:对于“同一个方法”,传入“不同对象”,实现了不同的效果
class Meizi {
public function meet($obj) {
//限制了对象必须有qinqin()这个方法
if( $obj instanceof Hanzi){
//同一个方法
$obj->qinqin();
}else{
echo '你不会亲亲这个功能!';
}
}
}
//抽象类
abstract class Hanzi
{
abstract public function qinqin();
}
//大屌丝类
class DDS extends Hanzi {
public function qinqin() {
echo '被妹子打了一巴掌,这就是DDS的命运';
}
}
//高富帅类
class GFS extends Hanzi {
public function qinqin() {
echo '不仅仅亲亲,还啪啪啪,这是高富帅的命运';
}
}
//萌妹子类
class MengMeizi {}
$m = new Meizi;
$dds = new DDS;
$gfs = new GFS;
$mmz = new MengMeizi;
//传入对象
echo $m->meet($dds); //实现了DDS的效果
echo $m->meet($gfs); //实现了GFS的效果
//没有限制
echo $m->meet($mmz); //你不会亲亲!
@@多态的两个实例:
./1.通过接口实现多态的应用.php
./2.通过普通类实现多态的应用.php
===================================================
十三、异常处理:
在php5中有一种新的错误处理机制--异常处理:(采用面向对象方式的)
涉及的类:Exception异常类
Exception类结构:
class Exception
{
protected $message = 'Unknown exception'; // 异常信息
protected $code = 0; // 用户自定义异常代码
protected $file; // 发生异常的文件名
protected $line; // 发生异常的代码行号
function __construct($message = null, $code = 0);
final function getMessage(); // 返回异常信息
final function getCode(); // 返回异常代码
final function getFile(); // 返回发生异常的文件名
final function getLine(); // 返回发生异常的代码行号
final function getTrace(); // backtrace() 数组
final function getTraceAsString(); // 已格成化成字符串的 getTrace() 信息
/* 可重载的方法 */
function __toString(); // 可输出的字符串
}
使用:
try{
throw new Exception("年龄不可以为负数"); //异常抛出
}catch(Exception $e){
//异常处理
echo $e->getmessage();
}
实例:
function addUser($username) {
if($username="xiaobai") {
//添加成功
}else {
//添加失败
throw new Exception('添加失败');
}
}
function updateUser($username) {
if($username = "xiaohei") {
//修改成功
}else {
//修改失败
throw new Exception('修改失败');
}
}
try {
addUser('xiaobaia');
updateUser('xiaohei');
}catch(Exception $e) {
echo '失败信息是:'.$e->getMessage();
}
@@当捕获到一个异常后,try()块里面的后续代码不继续执行