1.1.1. 08.类与对象3


1.重载与重写

重写是指覆盖原方法,一般用于子类继承父类重写父类方法。

PHP 提供的“重载”是动态的“创建”类的属性和方法。通过使用魔术方法来实现。

当调用当前环境下未定义的属性和方法是,则会调用魔术方法。

在给不可访问属性赋值时,__set() 会被调用。

读取不可访问属性的值时,__get() 会被调用。

当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。

当对不可访问属性调用 unset() 时,__unset() 会被调用。

在对象中调用一个不可访问方法时,__call() 会被调用。

在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。

<?php
    class demo{
        private $a = 'a';

        public function __get($name){
            return $this->$name;
        }
        public function __set($name,$value){
            $this->$name=$value;
        }

        public function __isset($name){
            echo "isset $name".PHP_EOL;
        }

        public function __unset($name){
            echo "unset $name".PHP_EOL;
        }

        public function __call($name,$args){
            $args = implode(',', $args);
            echo "call $name ,args is {$args}".PHP_EOL;
        }

        public static function __callStatic($name,$args){
            $args = implode(',', $args);
            echo "call static $name ,args is {$args}".PHP_EOL;
        }
    }

    $obj = new demo();
    $obj->a = 'b'; 
    echo $obj->a.PHP_EOL; // b
    isset($obj->a); // isset a
    unset($obj->a); // unset a
    $obj->say('Hello','World'); // call say ,args is Hello,World
    demo::staticSay('World','World'); // call static staticSay ,args is World,World

2.多态

统一操作,作用于不同对象,得到不同的结果。如数据库操作,$db->query(); 可以是 mysql 的操作,也可以是redis 的

<?php

    abstract class db{
        abstract function query();
    }

    class mysql{
        public function query(){
            echo 'query mysql'.PHP_EOL;
        }
    }

    class redis{
        public function query(){
            echo 'query redis'.PHP_EOL;
        }
    }


    function run($db){
        $db->query();
    }


    run(new mysql()); // query mysql
    run(new redis()); // query redis

3.遍历对象

遍历对象可以使用foreach遍历可见属性。或者实现iterator接口

<?php
    class MyClass
    {
        public $var1 = 'value 1';
        public $var2 = 'value 2';
        public $var3 = 'value 3';

        protected $protected = 'protected var';
        private   $private   = 'private var';

    }

    $c = new MyClass();

    foreach ($c as $key=>$v) {
      echo $key."=>".$v.PHP_EOL;
    }
    // var1=>value 1
    // var2=>value 2
    // var3=>value 3

4.魔术方法

  • __construct 初始化调用
  • __desturct 对象销毁时调用
  • __call 访问一个不存在的方法的时候调用
  • __callStatic 访问一个不存在的静态方法调用
  • __get() 访问一个不存在的属性调用
  • __set() 修改一个不存在的属性调用
  • __isset() 使用 isset 判断一个高属性的时候调用
  • __toString() 当一个对象以一个字符串返回时候触发调用
  • __invoke() 当把一个对象当函数去调用的时候触发
  • __sleep() 当使用 serialize() 时调用
  • __wakeup() 当使用 unserialize() 时调用
<?php

    class MyClass 
    {
        public $server = 'server';
        public function __invoke($a){
            var_dump($a);
        }
        public function __sleep(){
            return [$this->server];
        }
        public function __wakeup(){
            return $this->server;
        }
    }

    $c = new MyClass();

    $c(5); // int(5)

    var_dump($d = serialize($c)); // string(44) "O:7:"MyClass":1:{s:6:"server";s:6:"server";}"

    var_dump(unserialize($d)); //object(MyClass)#2 (1) {
                               // ["server"]=>
                               // string(6) "server"
                               // }

5.Final 关键字

被 final 修饰的类不能被继承。

如果一个类中某个方法被 final ,这个类不能被重写。

final 不能修饰属性。

<?php
    class A{
        final public function test(){}
    }

    Class B extends A{
      public function test(){ //error

      }
    }

6.对象的复制和比较

对象的复制通过 clone 关键字来完成。这将会调用 clone() 方法。对象中的 clone() 方法不能被直接调用

当对象被复制后,PHP 5 会对对象的所有属性执行一个浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。

当复制完成时,如果定义了 clone() 方法,则新创建的对象(复制生成的对象)中的 clone() 方法会被调用,可用于修改属性的值(如果有必要的话)。

<?php

    class MyClass 
    {
        public $a = 'a';
        public function __clone(){
            $this->a = 'b';
        }
        public function say(){
            echo $this->a.PHP_EOL;
        }
    }

    $a = new MyClass();
    $b = clone $a;
    $a->say(); // a
    $b->say(); // b

当使用比较运算符(==)比较两个对象变量时,比较的原则是:如果两个对象的属性和属性值 都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等。

而如果使用全等运算符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)

7.类型约束

函数的参数可以指定必须为对象(在函数原型里面指定类的名字),接口,数组

<?php
    abstract class db{
        abstract function query();
    }

    class mysql extends db{
        public function query(){
            echo 'query mysql'.PHP_EOL;
        }
    }

    class redis extends db{
        public function query(){
            echo 'query redis'.PHP_EOL;
        }
    }

    class demo{
        public function run(db $db){
            $db->query();
        }
    }

    $obj = new demo();
    $obj->run(new mysql()); // query mysql
    $obj->run(new redis()); // query redis

8.静态绑定

self 调用的方法是所定义的类所定义的方法。 static 调用的方法是调用类的方法。

<?php
    class Car
    {
        public static function staticModel()
        {
             static::getModel();
        }
        public static function selfModel()
        {
             self::getModel();
        }
        protected static function getModel()
        {
            echo "I am a Car!".PHP_EOL;
        }
    }

    class Mercedes extends Car
    {
        protected static function getModel()
        {
            echo "I am a Mercedes!".PHP_EOL;
        }
    }


    Car::staticModel(); // I am a Car!
    Mercedes::staticModel(); // I am a Mercedes!
    Car::selfModel(); // I am a Car!
    Mercedes::selfModel(); // I am a Car!

9.对象和引用

PHP 的引用是别名,就是两个不同的变量名字指向相同的内容。在 PHP 5,一个对象变量已经不再保存整个对象的值。只是保存一个标识符来访问真正的对象内容。 当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容。

<?php
    class A {
        public $foo = 1;
    }  

    $a = new A;
    $b = $a;     // $a ,$b都是同一个标识符的拷贝
                 // ($a) = ($b) = <id>
    $b->foo = 2;
    echo $a->foo."\n";
Copyright © Kagami丶 2019 all right reserved,powered by Gitbook该文件修订时间: 2019-10-17 23:12:59

results matching ""

    No results matching ""