美文网首页我爱编程
10.PHP 类与对象(二)

10.PHP 类与对象(二)

作者: 三生石的等待 | 来源:发表于2018-05-24 10:36 被阅读0次

    Static 关键字

    声明类成员或方法为 static,就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员(静态方法除外)。
    由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。静态属性不可以由对象通过 -> 操作符来访问。

    注意:在 PHP7 中通过(::)调用非静态方法会产生一个 E_DEPRECATED 级别的警告,不赞成这样使用,在以后可能会取消对这种用法的支持。

    <?php 
    class Test
    {
        public $hi = 'Hi';
        public static $hello = 'Hello';
    
        public function sayHi()
        {
            echo $this->hi;
        }
        public static function sayHello()
        {
            echo self::$hello;
        }
        public function sayWorld()
        {
            echo " World".PHP_EOL;
        }
    }
    
    $obj = new Test();
    $obj->sayHi();
    $obj->sayWorld();
    
    Test::sayHello();
    Test::sayWorld();
    

    从结果可以看出

    • 通过 :: 可以执行静态和非静态方法,但是不赞成通过这种方式调用非静态方法,此方式有可能被官方移除,因此上面 sayWorld(),应该通过 (new Test())->sayWorld() 这种方式调用
    • 静态属性和方法可以通过 self 关键字调用

    就像其它所有的PHP静态变量一样,静态属性只能被初始化为一个字符值或一个常量,不能使用表达式。 所以你可以把静态属性初始化为整型或数组,但不能指向另一个变量或函数返回值,也不能指向一个对象。

    抽象类

    定义为抽象的类可能无法直接被实例化,任何一个类, 如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。如果类方法被声明为抽象的, 那么其中就不能包括具体的功能实现。

    <?php
    
    abstract class Say
    {
        abstract public function sayHello($word);
        abstract public function sayHi();
    }
    
    class Speak extends Say
    {
        public function sayHello($word)
        {
            echo "Hello $word";
        }
    
        public function sayHi()
        {
            echo "Hi".PHP_EOL;
        }
    }
    
    $s = new Speak();
    $s->sayHi();
    $s->sayHello("World");
    

    从结果可以看出

    • 继承一个抽象类的时候,子类必须定义父类中的所有抽象方法。例如,在类 Speak 中移除方法 sayHi(),结果为
    Fatal error: Class Speak contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Say::sayHi)...
    
    • 这些方法的访问控制必须和父类中一样(或者更为宽松)。例如,在类 Speak 中 sayHi() 声明为 protected,则报错
    Fatal error: Access level to Speak::sayHi() must be public (as in class Say)...
    
    • 此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,移除抽象方法 sayHello() 中的参数,则
    Fatal error: Declaration of Speak::sayHello($word) must be compatible with Say::sayHello()...
    

    接口

    使用接口(interface),你可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。我们可以通过 interface 来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。 接口中定义的所有方法都必须是public,这是接口的特性。

    实现

    要实现一个接口,可以使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个 fatal 错误。如果要实现多个接口,可以用逗号来分隔多个接口的名称。

    <?php
    
    interface A
    {
        public function actionA();
    }
    
    interface B
    {
        public function actionB();
    }
    
    //实现多个接口
    class C implements A, B
    {
        public function actionA()
        {
            //do something
        }
        public function actionB()
        {
            //do something
        }
    }
    

    注意:

    • 实现多个接口时,接口中的方法不能有重名。
    • 接口也可以继承,通过使用 extends 操作符。

    常量

    接口中也可以定义常量。接口常量和类常量的使用完全相同。 它们都是定值,不能被子类或子接口修改。

    <?php
    interface A
    {
        const B = 'Interface constant';
    }
    
    // 输出接口常量
    echo A::B;
    
    // 错误写法,因为常量的值不能被修改。接口常量的概念和类常量是一样的。
    class C implements A
    {
        const B = 'Class constant';
    }
    

    匿名类

    php7支持通过new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。

    <?php
    interface Logger {
        public function log(string $msg);
    }
    
    class Application {
        private $logger;
    
        public function getLogger(): Logger {
             return $this->logger;
        }
    
        public function setLogger(Logger $logger) {
             $this->logger = $logger;
        }
    }
    
    $app = new Application;
    $app->setLogger(new class implements Logger {
        public function log(string $msg) {
            echo $msg;
        }
    });
    
    var_dump($app->getLogger());
    ?>
    

    相关文章

      网友评论

        本文标题:10.PHP 类与对象(二)

        本文链接:https://www.haomeiwen.com/subject/prpjjftx.html