PHP面向对象继承详解.docx
《PHP面向对象继承详解.docx》由会员分享,可在线阅读,更多相关《PHP面向对象继承详解.docx(13页珍藏版)》请在冰豆网上搜索。
PHP面向对象继承详解
PHP继承
定义两个类:
classBook{
public$goods_name;
public$goods_price;
public$author;
public$publisher;
}
classPhone{
public$goods_price;
public$goods_name;
public$brand;
public$mode;
}
书与电话有共同的属性,可以提取
classGoods{
public$goods_name;
public$goods_price;
}
因此在书类与电话类中这两个属性可以不用写,但书与电话类中就已经没有了这两个属性
于是就用到了继承:
继承定义:
如果一个对象A,使用了另一个对象B的成员,那么我们就称A对象继承了B对象
示例:
classGoods{
public$goods_name;
public$goods_price;
}
classBookextendsGoods{
public$author;
public$publisher;
}
$b=newBook;
var_dump($b);
输出结果为:
object(Book)#1(4){["author"]=>NULL["publisher"]=>NULL["goods_name"]=>NULL["goods_price"]=>NULL}
语法:
使用关键字:
extends让一个类继承自另一个类
TIPS:
继承概念体现在对象上,语法体现在类上
此时,特定的称谓:
以上的示例中:
Goods:
称类为父类,基础类
Book:
称为子类,扩展类
语法意义就是面向对象中的代码重用!
单继承
指的是,一个类,只能存在一个父类(基础类),不能同时继承多个类
下面的这种继承就是错误的:
classStoreBookextendsGoods,Book{
public$age=3;
}
instanceof,是否是某类实例
体现:
一个对象如果是子类的实例,同时也是父类的实例!
(实例,通过该类实例化的对象)
重写,是个现象!
classGoods{
public$goods_name='ginvip';
public$goods_price;
}
classBookextendsGoods{
public$goods_name='《gin-php》';
public$author;
public$publisher;
}
$b1=newBook;
var_dump($b1);
输出结果为:
object(Book)#1(4){["goods_name"]=>string(13)"《gin-php》"["author"]=>NULL["publisher"]=>NULL["goods_price"]=>NULL}
如果子类与父类出现同名的成员(属性方法),则在实例化子类对象时,只会得到子类中定义的成员,称之为重写!
方法也可以重写:
classGoods{
public$goods_name='ginvip';
public$goods_price;
publicfunctionSayPrice(){
echo$this->goods_price;
}
}
classBookextendsGoods{
public$goods_name='《gin-php》';
public$author;
public$publisher;
publicfunctionSayPrice(){
echo'&',$this->goods_price;
}
}
$b1=newBook;
$b1->goods_price=1234.15;
$b1->SayPrice();
输出结果为:
&1234.15
一旦重写,父类的代码就不会执行!
但是,有些方法是一定会重写的,典型的是构造方法:
classGoods{
public$goods_name='ginvip';
public$goods_price;
publicfunction__construct($name,$price){
$this->goods_name=$name;
$this->goods_price=$price;
}
}
classBookextendsGoods{
public$goods_name='《gin-php》';
public$author;
public$publisher;
publicfunction__construct($author,$publisher){
$this->author=$author;
$this->publisher=$publisher;
}
}
$b1=newBook('BruceLee','ginvip','PHP',1234.56);
echo'<pre>';
var_dump($b1);
echo'</pre>';
输出结果为:
object(Book)#1 (4) {
["goods_name"]=>
string(13) "《gin-php》"
["author"]=>
string(9) "Bruce Lee"
["publisher"]=>
string(6) "ginvip"
["goods_price"]=>
NULL
}
怎样才能调用父类的构造方法呢?
parent,父类
parent关键字,表示父类的意思!
用于在当前类中,强制调用父类成员!
典型的做法:
将参数传递到子类的构造方法中,再在子类中,强制使用parent关键字调用父类的构造方法
classGoods{
public$goods_name='ginvip';
public$goods_price;
publicfunction__construct($name,$price){
$this->goods_name=$name;
$this->goods_price=$price;
}
}
classBookextendsGoods{
public$goods_name='《gin-php》';
public$author;
public$publisher;
publicfunction__construct($author,$publisher,$name,$price){
//父类构造方法
parent:
:
__construct($name,$price);
$this->author=$author;
$this->publisher=$publisher;
}
}
$b1=newBook('BruceLee','ginvip','PHP',1234.56);
echo'<pre>';
var_dump($b1);
echo'</pre>';
输出结果为:
object(Book)#1 (4) {
["goods_name"]=>
string(3) "PHP"
["author"]=>
string(9) "Bruce Lee"
["publisher"]=>
string(6) "ginvip"
["goods_price"]=>
float(1234.56)
}
注意:
self,parent,$this的区别
self:
:
当前类本身
parent:
:
当前父类
$this->当前对象
$this的确定:
看上面的parent,或者父类名
与:
“只有在使用对象调用非静态方法时,才可以使用$this
静态方法,无论如何也不能对$this做处理
而非静态方法,只有确定了对象,才能确定$this的值!
”
$this确定的基本原因:
1:
哪个对象调用方法,方法内的$this就是那个对象
2:
对象环境,是可以向下传递的
如果当前方法内,已经确定了对象环境,在该方法内,如果出现了静态调用非静态方法,那此时,当前的对象环境,会传递到被静态调用的非静态方法中
面试题:
$this永远代表所在的类对象么?
答:
不是
访问修饰限定符:
public,protected,private
public:
公共的
protected:
保护的
private:
私有的
用于描述一个成员(属性,方法)在哪里才能被访问的!
注意:
PHP是采用类的概念,进行成员的限制访问的
PHP将访问的代码分成三大区域:
类内,类外,继承链上类内
是根据:
成员在哪里定义与成员在哪里访问来决定类内,类外还是继承链上类内
以属性$property为例:
示例代码:
classA{
publicfunctionin_a_func(){
var_dump($this->property);//在A类中,父类中(继承链)访问
}
}
classBextendsA{
//成员定义在B类
public$property='publicproperty';
publicfunctionin_b_func(){
var_dump($this->property);//在本类内访问
}
}
classCextendsB{
publicfunctionin_c_func(){
var_dump($this->property);//在C类内访问,在子类(继承链)上访问
}
}
//$property成员定义在B类
$c=newC;
var_dump($c->property);
$c->in_c_func();
$c->in_b_func();
$c->in_a_func();
public
公共的,指的是,成员在本类内,继承链上的类内,与类外都可以被访问
protected
保护的,指的是,成员在本类内,继承链上的类内,可以被访问
private
私有的,指的是,只有本类内,可以访问
如何选择:
一个原则,尽量体现封装性。
封装性,指的是,尽量隐藏内部实现,而仅仅开放外部操作接口!
语法上,就是将不需要外部使用的属性,方法,都私有化(保护化),而仅仅留下一些必要的公共方法!
注意:
1:
重写的问题,一定要先明确访问的究竟是哪里所定义的
2:
私有成员的重写问题
私有成员不能被重写。
意味着,在相应的私有属性定义的类中,才能访问到相应的私有属性!
如:
classB{
public$public_p='inBpublic';
protected$protected_p='inBpublic';
private$property='inBprotectedproperty<hr/>';
publicfunctionin_b_func(){
var_dump($this->property);
}
}
classCextendsB{
public$public_p='inCpublic';
protected$protected_p='inCpublic';
private$property='inCprotectedproperty<hr/>';
publicfunctionin_c_func(){
var_dump($this->property);
}
}
$o=newC;
var_dump($o);
以上代码输出的结果为:
object(C)#1(4){
["public_p"]=>
string(11)"inCpublic"
["protected_p":
protected]=>
string(11)"inCpublic"
["property":
"C":
private]=>
string(29)"inCprotectedproperty<hr/>"
["property":
"B":
private]=>
string(29)"inBprotectedproperty<hr/>"
}
注意:
在处理私有属性时,一定要确定其定义位置!
建议是:
如果需要通过继承,就使用保护的,少用私有的!
在没有继承时,尽量使用私有的
3:
在重写时,如果重写成员的访问级别不一致
子类的级别比父类的级别,相等或者弱,可以
子类的级别比父类的级别,强,不可以
如:
classA{
protectedfunctionf1(){
echo 'inAf1';
}
}
classBextendsA{
privatefunctionf1(){
echo'inBf1';
}
}
$o=newB;
$o->f1();
输出结果为:
4:
兼容性的问题
早先的php的面向对象不完善,没有访问控制!
那时在声明属性时,使用var关键字,声明方法时,什么都不使用,直接function....
为了兼容,上面的做法还是可以使用!
var,functon的访问权限,都是public
因此,以下两段代码是一样的:
classC{
var$name;
functionf1(){
}
}
classD{
public$name;
publicfunctionf1(){
}
}