继承的基本概念
1.继承:一个类从另一个已有的类获得其特性,称为继承。
2.派生:从一个已有的类产生一个新的类,称为派生。
3.父类/子类:已有类为父类,新建类为子类。父类又可以称为“基类”、“上级类”。子类有称为“派生类”、“下级类”;
4.单继承:一个类只能从一个上级类继承其特性信息。PHP和大多数面向对象的语言都是单继承模式,C++是多继承。
5.扩展:在子类中再定义自己的一些新的特有的特性信息(属性、方法和常量)。没有扩展,继承也就没有意义了。
语法:
class 子类名 extends 父类名{
//类成员
}
举例:
class A{
public $x1 = 10;
public $x2 = 15;
function add(){
echo {$this->x1} + {$this->x2};
}
}
class B extends A{
public $x3 = 20;
}
访问控制修饰符
1.public 公共的:在所有位置都可以访问(使用)。
2.protected 受保护的:只能在该类内部和该类的子类或父类中访问(使用)。
3.private 私有的:只能够在该类内部访问(使用)。
访问控制修饰符的作用是:
用来“限制”其所修饰的成员的“可访问性”。
访问类的时候有三个访问位置:
1.某个类的内部.
2.某个类的继承类的内部.
3.某个类的外部.
访问控制修饰符与访问位置的关系
Table | 类内部 | 继承关系内部 | 类外部 |
---|---|---|---|
public | yes | yes | yes |
protected | yes | yes | no |
private | yes | no | no |
示例:
<?php
class A{
public $x1 = 10;
protected $x2 = 16;
private $x3 = 21;
function showInfo(){
echo $this -> x1; //类内部+public = 正确
echo $this -> x2; //类内部+protected = 正确
echo $this -> x3; //类内部+private = 正确
}
}
class B extends A{
function showInfo1(){
echo $this -> x1; //子类内部+public = 正确
echo $this -> x2; //子类内部+protected = 正确
echo $this -> x3; //子类内部+private = 出错
}
}
$obj1 = new A();
echo $obj1->x1; //类外部+public = 正确
echo $obj2->x2; //类外部+protected = 出错
echo $obj3->x3; //类外部+private = 出错
$obj1->showInfo(); //101621(内部建模成功,外部可调用)
?>
paren关键字
parent代表父类——代表父类这个类,而不是父类的对象。
使用方式
parent :: 属性或方法; //通常是静态属性或静态方法,但有时候也可以用实例属性或实例方法;
调用静态属性、方法示例:
<?php
class A{
static $p1 =1;
static pritected $p2 =2;
}
class B extends A{
static function Show1(){
echo "这里要调用父类属性$p1:".parent :: $p1;
echo "这里要调用父类属性$p2:".parent :: $p2;
}
}
B :: Show1();
?>
//结果:这里要调用父类属性 p1:1这里要调用父类属性 p2:2
调用实例属性、方法示例:
<?php
class C{
public $p3 = 10;
function Show2(){
echo $this->$p3;
}
}
class D{
function Show3(){
echo "调取父类方法";
parent :: Show2(); //调用了父类实例方法。成功调用的前提是,本方法(show3)的调用者是一个对象。
}
}
$boj1 = new D();
$obj1 -> Show3();
?>
//结果:调取父类方法 10
parent,self,$this的使用对比:
关键字 | 含义 | 使用位置 | 使用示例 |
---|---|---|---|
parent | 代表父类(这个类) | 肯定在一个方法中 | parent :: 属性或方法 |
self | 代表当前其所在的类 | 肯定在一个方法中 | self :: 静态属性或方法 |
$this | 代表调用当前方法的类 | 肯定在一个方法中 | $this -> 实例属性或方法 |
构造方法和析构方法的继承与调用问题
1.如果一个类有构造方法,则实例化这个类的时候,就不会调用父类的构造方法(如果有)。
2.如果一个类没有构造方法,则实例化这个类的时候,就会调用父类的构造方法(如果有)。
3.如果一个类有析构方法,则销毁这个类的时候,就不会调用父类的析构法(如果有)。
4.如果一个类没有析构方法,则销毁这个类的时候,就会调用父类的析构方法(如果有)。
5.如果一个类中有构造方法或析构方法,则就可以去“手动”调用父类的同类方法(如果有)。——这是构造方法的一种典型写法(在子类构造法中,常常需要去调用父类额构造方法,以简化对象的初始化工作)
手动调用的语法形式总是这样:
parent :: 构造方法或者析构方法。
1,2示例:
<?php
class A{
function __construct(){
echo "这是父类的构造方法。";
}
}
class B extends A{
function __construct(){
echo "这是子类的构造方法。";
}
}
class C extends A{
}
$obj1 = new B();
$obj2 = new C();
?>
//结果:这是子类的构造方法。 这是父类的构造方法。
5示例:
<?php
//公司成员
class Member{
public $name = "匿名";
public $age = 18;
public $sex;
function __construct($name,$age,$sex){
$this->name = $name;
$this->age = $age;
$this->sex =$sex;
}
}
//讲师
class Teacher extends Member{
public $edu = "大学";
public $major =;
function __construct($name,$age,$sex,$edu,$major){
parent :: __construct($name,$age,$sex);
$this->edu = $edu;
$this->major = $major;
}
function ShowInfo(){
echo "<br />姓名:{$this->name}";
echo "<br />年龄:{$this->age}";
echo "<br />性别:{$this->sex}";
echo "<br />学历:{$this->edu}";
echo "<br />专业:{$this->major}";
}
}
$obj1 = new Teacher('张飞',30,'男','小学','PHP');
$obj1->ShowInfo();
?>
//结果:
姓名:张飞
年龄:30
性别:男
学历:小学
专业:PHP
重写(覆盖)
重写又叫覆盖,就是将从父类继承袭来的属性或方法重新定义。
需要覆盖的原因,是因为父类的某个属性或者方法可能对于子类来说不够具体或详细,子类想要同样特性或功能的更准确或详细的信息。
重写的基本要求:
1.访问控制权限:
子类覆盖的属性或方法的访问控制权限,不能“低于”父类的被覆盖的属性或方法的访问控制权限,如下所示:
父类:public 子类:只能是public
父类:protected 子类:可是是protected和public
父类:private 子类:不能覆盖!
2.方法的参数形式:
子类覆盖父类同名方法的时候,参数要求跟父类保持一致。
注意:
1.私有属性和方法都不能覆盖,但子类可以定义跟父类私有的同名的属性或方法。这是会被当做一个资深的新的属性或方法来看待。但是方法的属性必须一致。(不推荐私有属性和方法的重名,新的为什么不起不同的名字?)
2.构造方法不但可以想其他普通方法一样重写,而且,比普通方法更宽松,重写的时候参数可以不一致。
示例:
<?php
class Phone{
public $num = "8位号码";
function tiJi(){
$tiji = "很大或中等大小";
}
class MobilePhone{
public $num = "11位号码";
function tiJi(){
$tiji = "很小";
}
}
}
?>
最终类和最终方法
最终类,是一种特殊要求的类:要求该类不允许往下继承,也就是说,该类不能作为父类被继承。
最终方法,就是一个不允许被下级类覆盖的方法。(可以被继承但不能被覆盖)
语法形式:
最终类:
final class 类名{
//类成员,跟一般类定义一样。
}
最终方法:
class 类名{
final function 方法名(形参){
//。。。
}
}
设计模式
简单来说,设计模式就是解决某个问题的一般性代码的“经验性总结”。(前人总结出来的)
工厂模式
所谓工厂模式,就是这样一个类(工厂类)——它可以根据“传递”给它的类名,而去生产对应的类的对象。(一种专门用于“生产”其他各种类的对象的一个类)
示例:
<?php
class A{}
class B{}
//设计一个工厂类,这个类有一个静态方法。通过该方法可以获得指定类的对象!
class GongChang{
static function GetObject($className){
$obj = new $className();
return $obj;
}
}
$o1 = Gongchang :: GetObject("A");//通过工厂类,此行相当于$o1 = new A();
$o2 = Gongchang :: GetObject("B");
$o3 = Gongchang :: GetObject("A");
?>
单例模式
例,就是实例,也就是对象。单例,就是一个对象。
单例模式:设计一个类,这个类只能“创造”它的一个对象。(实例)
单例3部曲:
1.私有化构造方法;
2.定义一个私有的静态变量,以储存唯一的对象;
3.定义一个静态方法,以判断是否需要进行实例化该唯一对象,并返回该对象。
示例:
<?php
//设计一个只能创造一个对象的类
class Single{
//1.创建一个构造方法,将这个类私有化,外部不能随便new。
private function __construct(){
}
//2.定义一个静态属性,初始值为null;这个属性要私有化,防止外部赋值。
static private $instance = null;
//3.定义一个静态方法,从中判断对象是否生产并适当返回该对象;
static function GetObject(){
//根据逻辑判断,控制对象数量只有一个,并“返回结果”
if(!isset(self :: $instance)){ //判断静态属性是否为空
$obj = new self(); //开始生产对象
self :: $instance = $obj; //将对象保存起来,让属性不为空
return $obj; //返回结果
}else{ //如果属性不为空,表示已经生产过了
return self :: $instance; //将已经生产好的对象返回给他。
}
}
}
$obj1 = Single :: GetObject();
$obj2 = Single :: GetObject();
var_dump($obj1);
var_dump($obj2);
?>
//结果:两个对象都指向同一个对象编号“#1”