PHPDay09:类的声明与实例化,封装继承多态,static,self,const,parent,魔术方法,魔术变量,抽象类

目录

0x00 类的声明

0x01 类的实例化:

0x02 成员变量的访问

0x03 $this

0x04构造和析构方法

0x05 面向对象三大特性:封装 继承 多态

0X06 常见关键字

1.static

2.self

3.const

4.parent

0x07魔术方法

9.序列化与反序列化

0x08 抽象类


0x00 类的声明

class 类名{
   修饰符 成员变量
   [修饰符] 成员函数
}

例如:

声明类时可以给成员变量赋值,也可以不赋值。

<?php
class Car{
    var $color = 'red';
    var $leg = 4;
    public $person = 7;
    function run(){
        echo '跑';
    }
    function push(){
        echo '拉'.$this->person.'人';
    }
}
$car = new Car;
echo $car->color;
?>

成员变量的修饰符:

成员变量前必须有修饰符!

var /public:公有变量,任何地方都可以访问。

private:私有变量,只有成员函数可以访问。也就是说私有变量不会被继承。

protected:保护变量,只有成员函数和子类可以访问。

成员函数可以不写修饰符,默认为public

0x01 类的实例化:

1.new 类名(参数1,参数2)

2.new 类名

3.new 类名()

底层:

每次实例化其实都是在堆内存中开一段内存来存储对象的数据,而对象名存储在栈内存段,指向堆内存中相应的数据,需要注意的是堆内存中只存成员函数名,指向存储在代码段的成员函数的代码。

0x02 成员变量的访问

注意:成员变量前不需要加$符

<?php
    echo $car->leg;
    echo $car->push();
?>

0x03 $this

在成员方法中调用成员属性,必须加$this

0x04构造和析构方法

1.构造方法:在类实例化的时候自动调用,初始化类

写法一:

[public] function __construct([参数]){

}

写法二:与类名相同的函数,在PHP7中已经废弃

[public] function 类名([参数]){
    xxxx
}
<?php
class Car{
    var $color ;
    var $leg;
    public $person;
    /*
    function __construct(){
        echo '无参构造'.'<br/>';
        $this->color = 'red';
        $this->leg = 10;
        $this->person = 100;
    }
    */
    public function __construct($_color,$_leg,$_person){
        echo '有参构造'.'<br/>';
        $this->color = $_color;
        $this->leg = $_leg;
        $this->person = $_person;
    }
    public function __destruct(){
        echo '析构函数';
    }
    public function show(){
        echo 'color:'.$this->color.'<br/>';
        echo 'leg:'.$this->leg.'<br/>';
        echo 'person'.$this->person.'<br/>';
    }
}
$car = new Car('green',4,120);
$car->show();
?>

2.析构方法:在对象被销毁时自动调用,用于资源的关闭,销毁文件句柄,或者链接。

public function __destruct(){

} 

0x05 面向对象三大特性:封装 继承 多态

1.封装体现在两点:

  1. 把属性和方法封装到类中,实现某种功能
  2. 属性和方法前加修饰符,进行访问的限制

2.继承

(1)子类的定义方法:

class 子类名 extends 父类名{

}

子类继承父类之后,子类的对象继承了父类的所有方法和属性。

(2)子类调用父类的方法

如果子类想要在成员函数中调用父类的成员方法,只需要这样写:

parent::父类的方法

虽然调用的父类的方法,但是PHP将使用当前类的属性值。

(3)覆盖

在子类中可以重载父类的方法,即子类的同名方法将覆盖父类的同名方法

注意:重载后的方法必须不能比原来的方法的修饰符小 private < protected < public

<?php
class Car{
    var $color ;
    var $leg;
    public $person;
    public function __construct($_color,$_leg,$_person){
        echo '有参构造'.'<br/>';
        $this->color = $_color;
        $this->leg = $_leg;
        $this->person = $_person;
    }
    public function __destruct(){
        echo '析构函数';
    }
    public function show(){
        echo 'color:'.$this->color.'<br/>';
        echo 'leg:'.$this->leg.'<br/>';
        echo 'person'.$this->person.'<br/>';
    }
}
class Truck extends Car{
    var $capacity;
    var $speed;
    public function __construct($color,$leg,$person,$capacity,$speed){
        echo '子类的构造函数';
        parent::__construct($color,$leg,$person);
        $this->capacity = $capacity;
        $this->speed = $speed;
    }
    public function show(){
        parent::show();
        echo 'capacity:'.$this->capacity.'<br/>';
        echo 'speed:'.$this->speed.'<br/>';
    }
    public function push(){
        echo '我的最大载重为'.$this->capacity.'<br/>';
    }
}
$car = new Car('green',4,120);
$car->show();
$cyber_truck = new Truck('gray',8,10,100,2000);
$cyber_truck->show();
$cyber_truck->push();
?>

(4)final关键字:

final function 函数名(){

}

表示该成员函数是最终版本,子类中不能覆盖父类中的该函数,如果尝试覆盖,将会报错

final class 类名{

}

表示该类是最终版本,禁止其他类继承该类。如果尝试继承,则会报错。

3.多态

(1)instanceof

用于确定一个PHP变量是不是属于某一类class的实例,返回bool

$bus  = new Bus;
var_dump($bus instanceof Bus);

如果一个对象是一个子类的实例,那么它也是其父类的实例。

(2)如果不用多态,需要大量的流程控制语句。并且假如之后你需要增加一个类class Upan(),那么就需要修改接口test中的代码。

<?php
class Mobile{
    function doMobile(){
        echo '手机充电';
    }
}
class Mouse{
    public function doMouse(){
        echo '实现mouse的功能';
    }
}
class KeyBoard{
    public function doKeyBoard(){
        echo '实现KeyBoard的功能';
    }
}
function test($obj){
    if($obj instanceof Mobile){
        $obj->doMobile();
    }elseif($obj instanceof Mouse){
        $obj->doMouse();
    }elseif($obj instanceof KeyBoard){
        $obj->doKeyBoard();
    }else{
        echo 'error';
    }
}

$apple = new Mobile;
$keyboard = new KeyBoard;
$logic = new Mouse;
test($apple);
test($keyboard);
test($logic);

?>

但是如果改用多态,即便是之后要增加一个类,也不要修改接口test的代码。

<?php
class Device{
    public function work(){
        echo '这里面内容没用,子类要覆盖';
    }
}
class Mobile extends Device{
    function work(){
        echo '手机充电';
    }
}
class Mouse extends Device{
    public function work(){
        echo '实现mouse的功能';
    }
}
class KeyBoard extends Device{
    public function work(){
        echo '实现KeyBoard的功能';
    }
}
function test($obj){
    if($obj instanceof Device){
        $obj->work();
    }else{
        echo 'error';
    }
}

$apple = new Mobile;
$keyboard = new KeyBoard;
$logic = new Mouse;
test($apple);
test($keyboard);
test($logic);

?>

0X06 常见关键字

1.static

可以修饰成员属性和成员方法

<?php
class A{
    public static $a = 'hello world';
    public static function test(){
        echo 'test';
    }
    public function run(){
        //A::test();//或者写成static::test();或者self::test();
        self::test()
        echo A::$a;
    }
}
echo A::$a;
A::$a = 'xidian'
A::test();

$aaa = new A;
A.run();

?>

对于成员函数在static之后/之前还可以加上public protected等修饰符

静态属性和静态方法不需要类的实例化,就可以直接调用

类名::属性名

类名::方法名()

同时也可以在成员函数中通过上述方式调用静态方法 或者使用 静态属性。

2.self

可以访问本类中的静态属性 和 静态方法 以及 常量,在类中使用,不需要实例化。

self::静态属性

self::静态方法

用self比用类名好,因为如果类名修改了的话,那么类中用类名调用的静态方法、静态属性的语句都需要修改。

建议用self调用静态属性和静态方法,不要用类名也不要用static

self 和 static的区别:

self就是写在哪个类里面,实际调用的就是这个类

static代表使用的这个类,就是你在父类里写的static,然后被子类覆盖,使用的就是子类的方法或属性

<?php
class A{
    public static $a='hello world';
    public static function test(){
        echo "A's test";
    }
    public function run(){
        static::test();
    }
}
class B extends A{
    public static function test(){
        echo "B's test";
    }
}
$bbb = new B;
$bbb->run();//B's test

?>

如果将static改为self,将打印A‘s test

3.const

定义常量的两种方式:

常量不需要加$


<?php
define ('PI1',3.14);
const PI2 =3.14; 
?>

define 用于在类的外部定义常量,const用于在类的内部定义常量

<?php
class A{
    const NAME = 'xidian';
    public static function test(){
        echo self::NAME;
    }
}
echo A::NAME;
?>

访问类中的常量和访问类中的静态变量一样。

类的外部:

类名::常量名

类的内部:

self::常量名(推荐)

static::常量名

类名::常量名

4.parent

如果想要在子类中调用父类的方法,只要:

parent::方法名

5.clone

将对象赋值给对象不能直接使用等号,必须加上clone关键字

class A{
    public function test(){
        echo 'AAAA';
    }
}

$a1 = new A;
$a2 = $a1//error
$a2 = clone $a1;

0x07魔术方法

复习:

八大魔术常量:它们的值会随着它们在代码中的位置的改变而改变

  1. __LINE__:返回文件中的当前行号,也可以写成__line__
  2. __FILE__:返回当前文件的绝对路径(包含文件名)
  3. __DIR__:返回当前文件的绝对路径(不包含文件名),等价于dirname(__FILE__)
  4. __FUNCTION__:返回当前函数(或方法)的名称
  5. __CLASS__:返回当前的类名(包括该类的作用区域或命名空间)
  6. __TRAIT__:返回当前的trait名称(包括trait的作用区域或命名空间)
  7. __METHOD__:返回当前的方法名(包括类名)
  8. __NAMESPACE__:返回当前文件的命名空间的名称。

8大魔术方法:

1.__set($name,$val):用于在类的外部给私有变量赋值,相当于重载了给私有变量赋值的等号,当调用给私有变量赋值的等号的时候,实际上调用的是__set($name,$val)函数。

其中私有变量名会赋值给$name ,等号之后的值会赋值给$val;

<?php
class A{
    private $a;
    private $b;
    public function __construct($_a,$_b){
        $this->a = $_a;
        $this->b = $_b;
    }
    public function __set($name,$value){
        $this->$name = $value;
    }
    public function __get($name){
        return $this->$name;
    }
    public function show(){
        echo $this->a;
        echo $this->b;
    }
}
$aaa = new A(456,789);
//$aaa->show();
echo $aaa->b;
?>

2.__get($name):凡是在类外需要访问私有变量值的操作,都会自动调用__get()方法

3.__isset() :一般不用

4.__unset():一般不用

5.__call($name,$param):当调用不存在的方法时,会自动调用该方法。

$name = 方法名

$param = 参数 (以数组的形式)

一般在设计框架的时候,经常用该魔术方法。

6.__callstatic($name,$param):当调用不存在的静态方法时,会自动调用该方法。

<?php
class A{
    private $a;
    private $b;
    public function __call($method,$param){
        echo $method.'方法不存在';
    }
    public function static __callstatic($method,$param){
        echo '静态方法:'.$method.'不存在';
    }

}
$aaa = new A(456,789);
$aaa->test();
A::fuck();
?>

7.__clone() 克隆

当调用clone关键字的时候,会自动调用__clone方法。

相当于:实现克隆功能+实现__clone方法中的代码

<?php
class A{
    private $a;
    private $b;
    public function __clone(){
        echo 'hello world';
    }

}
$aaa = new A(456,789);
$bbb =  clone $aaa;
echo '<br/>';
var_dump($bbb);
echo '<br/>';
var_dump($aaa);

?>

注意:以上代码克隆功能并没有失效。

8.__toString

当在外部echo 对象时自动调用该方法。

<?php
class A{
    private $a;
    private $b;
    public function __toString(){
        return 'hello world';
    }

}
$aaa = new A(456,789);
echo $aaa;
?>

9.序列化与反序列化

如果直接echo数组,那么只会输出array。

如果偏要echo出数组,就必须先将数组序列化后,再echo

<?php
$arr = ['welcome','to','xidian'];
$after = serialize($arr);
echo $after;
//a:3:{i:0;s:7:"welcome";i:1;s:2:"to";i:2;s:6:"xidian";}
$before = unserialize($before);
print_r($before);
?>

a表示array,3表示数组的长度

序列化之后的数据可以直接存到数据库中。同样也可以从数据库中抽出来,通过反序列化,还原为原来的形式

对于 类 ,我们可以在 __toString()方法中将类序列化,这样类也能echo了

<?php
class A{
    private $a;
    private $b;
    public function __toString(){
        return serialize($this);
    }

}
$aaa = new A(456,789);
echo $aaa;
?>

0x08 抽象类

抽象方法:没有函数体的方法。用abstract修饰

含有抽象方法的类就是抽象类。用abstract修饰.

抽象类不能被实例化。抽象类是用来被继承的。天生就是用来当爹的。

而抽象方法是用来被重载的。在子类中需要重载抽象方法。

<?php
abstract class A{
    public $name = 'xidian';
    public abstract function test();
    public function run(){
        echo 'hello world';
    }
}
class B extends A{
    public function test(){
        echo 'hello xidian';
    }
}
$b = new B;
$b->run();
$b->test();
?>
发布了156 篇原创文章 · 获赞 19 · 访问量 8950

猜你喜欢

转载自blog.csdn.net/weixin_43415644/article/details/103842309
今日推荐