继承
继承:是指以一个类作为父类,另一个类可以作为其子类,
子类在继承了父类的属性/方法的基础上,进一步增添或修改
<?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
三者的区别:
| 访问范围 | private | protected | public |
|---|---|---|---|
| 本类内 | y | y | y |
| 子类内 | n | y | y |
| 类外 | n | n | y |
注意:在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();