四、PHP进阶学习之对象

78. 对象与类的简介

对象和数组的区别,对象不仅可以存储多个数据,还可以存储函数。

什么是对象?
世间万物皆对象,对象就是一个实体,在生活中可以描述出来的东西。如:电脑、桌子、小鸟。

对象中有什么?
对象有属性,如:小鸟有翅膀,有嘴巴。。。
对象有方法,如:小鸟会飞,小鸟会吃东西。。。

什么是类?
类是对象的模型,每一个对象都是根据一个类造出来的。类是对象的声明,对象是类的实例。类是抽象的,代表一类事物,现实生活中的具体事物。

OOP,面向对象编程,达到了代码变编程的重用性、灵活性和可扩展性。

面向过程,项目最小单位由函数组成。
面向对象,项目最小单位由对象组成。

79. 对象声明与使用

类的声明:
修饰符 class 类名{
成员
}

实例化对象:
变量 = new 类名();

<?php
class Bird{
	public $wing = 2;
	public function fly(){
		if($this->wing >= 2){
			echo '可以飞';
		}else{
			echo '飞不了';
		}
	}
}

class Doctor{
		public function fixed($bird){
			$wing = (int)mt_rand(1, 2);
			$bird->wing = $wing;
		}
}

$bailu = new Bird();
$wang = new Doctor();

echo $bailu->wing;
echo '<br>';

$bailu->fly();
echo '<br>';

$wang->fixed($bailu);
echo $bailu->wing;
echo '<br>';

$bailu->fly();
?>

80. 构造函数、析构函数

__construct(),构造函数,在实例化对象时自动调用,一般用于初始化对象。
__destruct(),析构函数,销毁对象或对象使用完毕时调用,一般用于释放内存等操作。

例:

class Human{
	public $name;
	public $gender;
	public function __construct($name, $gender){
		$this->name = $name;
		$this->gender = $gender;
		echo '对象构造完毕';
	}
	
	public function sayHi(){
	    echo 'Hello, my name is '. $this->name;
	}

	public function __destruct(){
		echo '该对象已经被销毁';
	}
}

$zhangsan = new Human('张三', '女');
$zhangsan->sayHi();
// unset($zhangsan);			// 手动销毁对象

总结:

  1. 构造函数,__construct(),可以有参数,以便初始化对象
    在 new 对象时,自动执行。
    new 对象时,
    ① 申请内存
    ② 如果有构造函数,先执行构造函数
    ③ 返回该对象的地址
  2. 析构函数,__destruct()
    对象销毁时,执行。一般在文件最后会自动销毁对象,也可以手动销毁。
    对象销毁:
    $a = new Human();
    $a 并不是对象,它只是一个变量名,指向对象。unset($a) 未必销毁了对象,一个对象如果还有其它变量来引用,unset($a) 并不会销毁,当引用为0,对象才销毁。
  3. $this 意义
    $this 指向调用方法的对象。
    $a->sayHi()、
    sayHi(){} 函数体内的 $this->name
    注:方法内,存取对象的属性值时,必须用 $this。

81. 面向对象之封装性

封装性,把对象成员属性、成员方法结合在一起,形成一个不可分割的独立单元,把这个独立单元的内部细节对外隐藏起来,对开放有限的接口供外界访问使用。

<?php
class Human{
	private $money = 1000;
	private $bank = 2000;
	// 从银行里面取钱
	private function getBank($n){
		if($n <= $this->bank){
			$this->bank -= $n;
			return $n;
		}
		return 0;
	}

	// 借钱给别人
	public function send($much){
		if($much <= 1000){
			$this->money -= $much;
		}elseif($much <= $this->money + $this->bank){
			$num = $much - $this->money;
			$this->money += $this->getBank($num);
			$this->money -= $much;
		}else{
			echo '对不起,钱不够';
			return false;
		}
		return $much;
	}
}


$lisi = new Human();
$m = $lisi->send(300);
if($m){
	echo '借了'. $m .'元';
}
?>

如何判断属性、方法 有没有访问权限?
看访问位置:
private 只能在类定义的大括号 {} 内,才能访问。
public 在任意位置都可以用对象访问。

82. 封装mysql类

<?php
error_reporting(0);		// 把错误报告等级设置为0

class mysql{
	private $host;
	private $user;
	private $pwd;
	private $dbname;
	private $charset;
	private $conn = NULL;		// 连接资源

	// 构造函数,初始化
	public function __construct(){
		$this->host = 'localhost';
		$this->user = 'root';
		$this->pwd = 'root';
		$this->dbname = 'test';
		$this->charset = 'utf8';
		$this->connect($this->host, $this->user, $this->pwd);
		$this->switchDb($this->dbname);
		$this->setchar($this->charset);
	}

	// 连接数据库
	private function connect($h, $u, $p){
		$conn = mysql_connect($h, $u, $p);
		$this->conn = $conn;
	}

	// 发送命令
	private function query($sql){
		return mysql_query($sql, $this->conn);
	}

	// 换库
	public function switchDb($dbname){
		$sql ='use '. $dbname;
		return $this->query($sql);
	}

	// 选字符编码
	public function setchar($char){
		$sql = 'set names '. $char;
		$this->query($sql);
	}

	// 取全部数据
	public function getAll($sql){
		$list = array();
		$rs = $this->query($sql);
		if(! $rs){
			return false;
		}
		while($row = mysql_fetch_assoc($rs)){
			$list[] = $row;
		}
		return $list;
	}

	// 取一行数据
	public function getRow($sql){
		$rs = $this->query($sql);
		if(! $rs){
			return false;
		}
		$row = mysql_fetch_row($rs);
		return $row[0];
	}

	// 关闭连接
	public function close(){
		mysql_close($this->conn);
	}
}

$mysql = new mysql();		// 实例化MySQL类
// 查询前十位客户的名字
$sql = 'select cu_name from customer limit 10';
$result = $mysql->getAll($sql);
var_dump($result);

// 查询客户的平均年龄
$sql = 'select ceil(avg(cu_age)) from customer';
$result = $mysql->getRow($sql);
var_dump($result);
?>

83. 面向对象之继承性

子类 extends 父类{}

  • 只能继承自一个父类。
  • 对于子类继承父类的 protected / public 属性、方法:
  1. 父类有的,子类继承
  2. 父类有的,子类可以更改
  3. 父类没有的,子类可以添加
  • 子类继承父类的 private 属性、方法:
    可以继承过来,但无权修改。

继承后,权限只能越来越宽松或不变,不能严格。

构造方法也可以继承,继承原则和普通方法一样。
如果子类也声明构造方法,则父类的构造方法被覆盖了。
如果父类的构造方法被覆盖了,自然,只执行子类中的新的构造方法。

如果是一个数据库操作类,或者model类,肯定是继承过去再用,不能直接操作model类。而model类又做了许多初始化的工作。
重写的model类的构造方法,导致初始化工作完不成时,如果子类继承时,子类有构造,为了保险起见,先调用父类的构造,例:
parent::__construct();

public、private、protected 权限:

privateprotectedpublic
本类内
子类内
外部

84. 面向对象之多态性

多态性,是指不同类的对象对同一事件作出不同的响应。即,同一个操作根据不同的操作对象而产生不同的效果。

<?php
class Light{
	public function open(Glass $g){
		$g->display();
	}
}

class Glass{
	public function display(){
		echo '发光';
	}
}

class RedGlass extends Glass{
	public function display(){
		echo '照红光';
	}
}

class BlueGlass extends Glass{
	public function display(){
		echo '照蓝光';
	}
}

class GreenGlass extends Glass{
	public function display(){
		echo '照绿光';
	}
}

$light = new Light();
$red = new RedGlass();
$blue = new BlueGlass();

$light->open($red);

$light->open($blue);
?>

85. 静态属性/方法

在属性和方法前,加 static 修饰,这种称为静态 属性/方法。

普通属性包在类内,用 对象->属性名 访问。
静态属性在类内,类声明完毕,该属性就已存在,不需要依赖于对象而访问。类在内存中只有一个,因此,静态属性也只有一个。

普通方法存放在类内,只有一份,需要对象去调用,属于对象,需绑定 $this 。
静态方法存在于类内,只有一份,不属于哪个对象,属于类。因此,不需要去绑定 $this ,通过类名就可以调用。

类 —— 访问 静态方法 ,可以
类 —— 方位 动态方法 ,方法内没 this 的情况下,但严重不支持,逻辑上解释不通
对象 —— 访问 动态方法,可以
对象 —— 访问 静态方法,可以

<?php
class A{
	function foo(){
		if(isset($this)){
			echo '$this is defined (';
			echo get_class($this);
			echo "). \n";
		}else{
			echo '$this is not defined. \n';
		}
	}
}

class B{
	function bar(){
		A::foo();
	}
}


$a = new A();
$a->foo();	// foo 是普通方法, $a 绑定到 $this ,属于 A类 
A::foo();	// 这样调用不规范,不绑定 $this

$b = new B();
$b->bar();	// bar 是普通方法, $b 绑定到 $this , b(){A::foo()} 这里静态调用,不操作 $this
B::bar();	//不绑定 $this
?>

86. self-parent

self 当前类(不是本对象)
parent 当前类的父类

例:

<?php
class cHuman{
	static public $money = 100;
	public function say(){
		echo Human::money;
	}
}

class customer extends cHuman{
	static public $money = 1000;
	public function say(){
		echo self::$money;
		echo '<br>';
		echo '父类只有', parent::$money;
	}
}

$zhangsan = new customer();
$zhangsan->say();
?>

从上面代码的运行结果,可以看出,self 和 parent 是有区别的。

再如:

<?php
class A{
	public function a1(){
		echo 'this is class function a1';
	}
}

class B extends A{
	public function b1(){
		echo $this->a1();
	}
	
	public function b2(){
		echo parent::a1();
	}
}
$b = new B();
$b->b1();
$b->b2();
?>

显示效果一样,但从面向对象角度看,继承过来的,就是自己的, $this 更符合面向对象的思想。

87. 单例模式

单例模式是一种常见的设计模式。核心结构中,只包含一个称为单例的特殊类。通过单例模式,可以保证系统中一个类只有一个实例,即一个类只有一个对象。

实现思路:
① 不让外部通过 new 来实例化:构造器私有化、保护
② 通过内部的 static 方法来调用实例化,并且,把实例保存在类内部的静态属性上
③ 防止对象的克隆:克隆方法私有化、保护
总结:三私一公

<?php
class Single{
	public $hash;
	static protected $ins = NULL;
	final protected function __construct(){
		$this->hash = mt_rand(1, 99999);
	}

	static public function getInstance(){
		if(! self::$ins instanceof self){
			self::$ins = new self();
		}
		return self::$ins;
	}
}

$s1 = Single::getInstance();
$s2 = Single::getInstance();
var_dump($s1);
var_dump($s2);

if($s1 == $s2){
	echo '是同一个对象';
}else{
	echo '不是同一个对象';
}
?>

88. final

final 不可修饰属性
final + 方法:可继承,不可重写
final + 类:不能继承自最终的类,即final类不能被继承

<?php
final class Human{}
class stu extends Human{}
// 将报错,因为final类不能被继承
?>
<?php
class Human{
	final public function say(){
		echo '123';
	}

	public function show(){
		echo '456';
	}
}

class Stu extends Human{}

$ming = new Stu();
$ming->say();		// final 方法可以被继承

class FreshMan extends Stu{
	public function say(){
		echo '789';		// 出错,不可重写
	}
}
?>

89. abstract

抽象方法只有声明部分,没有方法体,即,没有 {} 。采用 ‘ ; ’ 结束
一个类中,只要有一个抽象方法,这个类就必须声明为抽象类。
抽象方法在子类中必须重写。

总结:

  1. 抽象类不能被实例化
  2. 有抽象方法的类一定是抽象类,类必须用 abstract 修饰
  3. 抽象方法不能有函数体,即 abstract function foo();
  4. 抽象类中的非抽象方法,可以被子类调用
  5. 非抽象子类继承抽象类,子类必须实现父类的全部抽象方法
  6. 抽象子类继承抽象类,无需继承父类的抽象方法
<?php
abstract class Animal{
    public $name = 'animal';	// 有抽象方法的类一定是抽象类;类必须要abstract修饰
    abstract function cry();	// 抽象方法不能有函数体
    public function getName(){
        echo '我的名字';
    }
}
// new Animal();   // 报错,抽象类不能被实例化

class Dog extends Animal {
    // 非抽象子类继承抽象类,子类必须实现父类的所有抽象方法
    public function cry(){
		// todo
    }
}

$dog = new Dog();
$dog->getName();    //抽象类中的非抽象方法可以调用

abstract class Cat extends Animal{
    // 抽象子类继承抽象类,无需继承父类的抽象方法
}
?>

90. 工厂模式

工厂模式,就是把创建对象的过程封装起来,进行工厂化管理。
工厂模式的优点就在于创建对象上。建立一个工厂(一个函数或一个类方法)来制造新的对象,它的任务就是把对象的创建过程都封装起来,创建对象不再是使用new的形式了。而是调用一个方法或函数。

<?php
class A{}
class B{}

function getObj($c){
	if($c == 'A'){
		return new A();
	}elseif($c == 'B'){
		return new B();
	}
}
?>

91. 魔术方法

、、、、、、、、

名称描述
__get()读取不可访问或不存在属性时被调用
__set()当给不可访问或不存在属性赋值时被调用
__isset()对不可访问或不存在的属性调用
__unset()对不可访问或不存在的属性进行unset时被调用
__clone()进行对象clone时被调用,用来调整对象的克隆行为
__toString()当一个类被转换成字符串时被调用
__call()调用不可访问或不存在的方法时被调用
__construct()构建对象的时被调用
__destruct()明确销毁对象或脚本结束时被调用
__autoload()加载一个未定义类时被调用
<?php
function __get($t){
	return $this->$t;
}

function __set($t, $a){
	$this->$t = $a;
}

function __toString(){
	return "name:". $this->name;
}
echo $p;

function __isset($t){
	return isset($this->$t);
}
isset($p->name);

function __clone(){}
$p2 = clone $p1;

function __call($fname, $arr){
	echo $fname .' 方法不存在';
	var_dump($arr);
}
?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值