继承

继承:是指以一个类作为父类,另一个类可以作为其子类,
子类在继承了父类的属性/方法的基础上,进一步增添或修改

<?php
//定义3个类,人类,学生类,律师类
class Human
{
	private $height = 160;

	public function cry(){
		echo '555<br />';
	}
}

class Stu
{
	private $height = 170;
	public $snum = '00134';

	public function cry(){
		echo '59啊59...';
	}
	
	public function study(){
		echo "good good study day day up";
	}
}

class Lawer
{
	private $height = 180;
	public $area = "经济案件";

	public function cry(){
		echo "555<br />";
	}

	public function bianhu(){
		echo "我的当事人是无罪的<br />";
	}
}

$zhoukou = new Human();
$zhoukou->cry();

$xiaoming = new Stu();
$xiaoming->cry();
$xiaoming->study();

$lizhuang = new Lawer();
$lizhuang->cry();
$lizhuang->bianhu();

思考:
1.学生和律师归根结底还是人,
自然,人的属性和方法,自然就有

2.虽然学生和律师是人,但比最原始的人,
又多了一些属性和方法

而我们目前写的3个类,
完成了第二点:即有原始人的属性,又有学生/律师的特有属性

但是没有很好的利用上第一点:
即:既然是人,那默认就应该有人的属性,
何必再重新声明一遍???

这里的代码,就有冗余!

如何达到学生/律师 默认就有人的属性,达到代码的重用和简介?

答:利用继承

继承语法

继承语法:
子类 extends 父类 {}

注意: 子类 只能继承自 一个父类

不能这样写: subClass extends Dog,Cat,Pig{}

<?php

class Human
{
	private $height = 160;

	public function cry(){
		echo '555<br />';
	}
}

/*
再声明一个学生类,学生本质上还是人
只不过是人类中稍微特殊的一个群体
即:人类的基础上,衍生出学生类
可以让学生类 继承自 人类
*/
class Stu extends Human
{}

$zhoukou = new Human();
$zhoukou->cry();

$ime = new Stu();
$ime->cry();
$ime->laugh();

思考:
在学生类中,cry和laugh 都没定义
为什么cry方法调用成功,
为什么laugh方法调用失败,

答:因为Stu类 继承自 Human类

现实中,继承的例子更多,
你同事高富帅,,某天开了个宝马
他没有宝马,但是他爹有宝马.

疑问思考

继承了那些东西?
子类可以做什么扩充?
构造函数如何继承的?
私有属性/方法如何继承

<?php 

class Human
{
	private $wife = "小甜甜";
	
	public function cry(){
		echo "5555<br />";
	}
}

class Stu extends Human
{
	public function subtell(){
		echo $this->wife;
	}
}

$lisi = new Stu();

$lisi->cry();//5555
//$lisi->tell();//
$lisi->subtell();//出错如下

/*
Notice: Undefined property: Stu::$wife in D:\wamp2\www\PHPoop\491extends3.php on line 25

问:父类不是有$wife属性吗?为什么没继承过来?
答:私有的属性,可以理解为不能继承,
(其实还是能继承过来的,只不过无法访问)

public protected private中,
public protected 都可以继承,并拥有访问和修改的权限
这就好比说,家产已经继承了,愿意卖就卖,愿意改就改.

而私有的,就像先祖的牌位一样,可以继承,
但是不能动,只能供着. 

*/

继承了哪些东西

继承时,继承了父类的protected/public属性/方法
完全继承过来,属于子类.

父类private属性可以被子类继承,但是不可修改

<?php

class Human
{
	public $age = 22;
	private $wife = "小甜甜";

	public function cry(){
		echo "5555<br />";
	}

	public function pshow(){
		echo $this->wife,'<br />';
	}
}

class Stu extends Human
{
	private $wife = '凤姐';
	public $height = 182;

	public function sshow(){
		parent::pshow();
		echo $this->wife;
	}
}

$ime = new Stu();
// print_r($ime);
$ime->sshow();


/*
思考:

如果把Stu类中的$wife属性去掉,什么效果?
答: 未定义的属性$wife

如果把Human类中的$wife属性去掉,又什么效果?
答: 没有权限访问Stu::private $wife属性
*/

子类继承父类的属性/方法,可以修改或增加

<?php
class Sixty
{
	protected $wine = '1斤';

	public function play(){
		echo "谈理想<br />";
	}
}


class Nine extends Sixty
{
	public function play(){
		echo "玩网游,宅~<br />";
	}

	public function momo(){
		echo "妹子,认识一下";
	}

	public function showWine(){
		echo $this->wine;
	}
}

$s9 = new Nine();
//echo $s9->wine,'<br />';//父类有的,继承过来
$s9->play();//父类有的,可以覆盖
$s9->momo();//父类没有的,可以添加
$s9->showWine();
/*
上面继承过来的大环境的大环境,
是指 protected/public
*/

继承时的权限变化

<?php
class Human
{
	public function cry(){
		echo "5555<br />";
	}
}

class Stu extends Human
{
	protected function cry(){
		echo "5959<br />";
	}
}

/*
Fatal error: Access level to Stu::cry() must be public (as in class Human) in D:\wamp2\www\PHPoop\491extends6.php on line 19

子类的cry比父类的cry方法权限要严格,
这不行,基础时,继承自父类的属性/方法的权限,只能越来越宽松
或保持不变,不能越来越严格!
*/

构造方法的继承

构造方法的继承
构造函数的继承:与普通方法的继承一样
进而,如果子类也声明构造函数,则父类的构造函数被覆盖
如果父类构造函数被覆盖了,自然,只执行子类中新的构造函数

引发一个问题:
如果是一个数据库操作类,或者model类
我们肯定是要继承过去再使用,不能直接操作model类
而model类的构造函数,又做了许多初始化工作,

我重写了model类,导致初始化工作完不成了.怎么办?
答:如果子类继承时,子类有构造函数,保险一点,在子类的构造函数中
调用 parent::__contruct();

这一点和java的面向对象,也有不同,
在java中,实例化子类时,父类的构造函数运行,且先运行,
然后运行子类的构造函数.

另外: java中构造函数不是__construct(),而是与类名
相同的方法理解为构造函数.

在一些比较老的教材或老的代码中,你也可能遇到下面的情况:
即:与类名相同的函数叫做构造函数 --这是php4时代的残留
请记住你不要这样写.

<?php
class Human
{
	
	public function __construct()
	{
		echo "呱呱坠地<br />";
	}
}

class Stu extends Human
{

}

//$ming = new Stu();//呱呱坠地,这说明构造函数也是可以继承的

class King extends Human
{
	public function __construct()
	{
		echo "红光满屋,终日不散<br />";
	}
}

$zhu = new King();


class Mysql
{
	protected $conn = NULL;
	
	public function __construct(){
		$this->conn = mysqli_connect('localhost','root','');
	}

	public function query ($sql){
		return mysqli_query($sql,$this->conn);
	}
}

$mysql = new Mysql();
var_dump($mysql->query('use test'));

class MyDb extends Mysql
{

	public function __construct(){
		//如果子类继承时,有构造函数,保险一点
		parent::__construct();
		//然后再写自己的业务逻辑
	}
	
	public function autoInser($sql)
	{
		return $this->query($sql);
	}
}


$mydb = new MyDb();

var_dump($mydb->autoInser('use test'));

权限操作符

  • private
  • protected
  • public

三者的区别:

访问范围privateprotectedpublic
本类内yyy
子类内nyy
类外nny

注意:在java中,如果属性/方法前面不写任何参数
即:public/protected/private都不写,则理解为friendly

在PHP中,如果public/protected/private 都不写,则理解为public

<?php
class Human
{
	private $name = "zhangsan";
	protected $money = 3000;
	public $age = 22;

	public function say(){
		echo "我叫",$this->name,'<br />';
		echo '我有',$this->money,'元<br />';
		echo "我今年",$this->age,"岁<br />";
	}
}

class Stu extends Human
{
	private $friend = '小花';

	public function talk(){
		echo "我叫",$this->name,'<br />';
		echo '我有',$this->money,'元<br />';
		echo "我今年",$this->age,"岁<br />";
	}
}

$ming = new Stu();
//$ming->friend;//Cannot access
//$ming->money;//Cannot access
echo $ming->age,'<br />';

/*
总结:
public可以在类外调用,权限最为宽松
protected和private不能在类外调用

public在类内可不可以调用???
答:当然可以,权限最为宽松,类内外都可以
*/

/*
下一行执行时:
Notice: Undefined property: Stu::$name in D:\wamp2\www\PHPoop\492quanxian.php on line 28

分析原因: Undefined property: Stu::$name 
这是说明Stu对象没有$name属性,

但是私有属性不是可以继承的吗?
答:是可以继承,但是系统有标记,标记其为父类层面的私有属性
因此无权调用,导致此错误发生


可以分析出:

protected可以在子类中访问,不可以在类外访问,

protected可以在子类中访问,本类能否访问?
答: 当然可以

*/
$ming->talk();

echo "<hr>";
$yuanmou = new Human();
$yuanmou->say();