天天看點

final 詳解

Final 關鍵字

PHP 5 新增了一個 final 關鍵字。如果父類中的方法被聲明為 final,則子類無法覆寫該方法。如果一個類被聲明為 final,則不能被繼承。

<?php
    final class Foo
    {
        public function doFoo()
        {
            return "foo->doFoo";
            // do something useful and return a result
        }
    }

    final class FooDecorator
    {
        private $foo;

        public function __construct(Foo $foo)
        {
            $this->foo = $foo;
        }

        public function doFoo()
        {
              $result = $this->foo->doFoo();
              // ... customize result ...
              return $result;
        }
    }

    $o = new FooDecorator(new Foo());
    var_dump($o->doFoo());

?>

output:
    string() "foo->doFoo"
           

Note: 屬性不能被定義為 final,隻有類和方法才能被定義為 final。

類被定義成 final 是不能被繼承的(當類定義成final的時候,方法這些預設就是final,是以可以不用final修飾)
方法定義成 final 是不能被覆寫的
final 關鍵字在PHP中不能用于類常量。使用關鍵詞'const'
final 關鍵字也不能修飾變量

)防止類繼承
)防止方法重寫或重編方法在子類
           

消除緊密耦合、使用最終的方法來替換類常量

緊密耦合示例(使用常量不好):
<?php
    interface FooInterface
    {
    }

    class Foo implements FooInterface
    {
        const BAR = ;

        public function __construct()
        {
        }
    }

    interface BazInterface
    {
        public function getFooBar();
    }

    // 這個類不能單獨進行單元測試,因為實際的類Foo也必須被加載以獲得Foo: BAR的值
    class Baz implements BazInterface
    {
        private $foo;

        public function __construct(FooInterface $foo)
        {
            $this->foo = $foo;
        }

        public function getFooBar()
        {
            return Foo::BAR;
        }

    }

    $foo = new Foo();
    $baz = new Baz($foo);
    $bar = $baz->getFooBar();
?>



松耦合示例(消除了常使用):

<?php
    interface FooInterface
    {
        public function bar();
    }

    class Foo implements FooInterface
    {
        public function __construct()
        {
        }

        final public function bar()
        {
            return ;
        }
    }

    interface BazInterface
    {
        public function getFooBar();
    }

    // 可以單獨測試這個類,因為類Foo不需要通過mock FooInterface和調用final bar方法來加載
    class Baz implements BazInterface
    {
        private $foo;

        public function __construct(FooInterface $foo)
        {
            $this->foo = $foo;
        }

        public function getFooBar()
        {
            return $this->foo->bar();
        }

    }

    $foo = new Foo();
    $baz = new Baz($foo);
    $bar = $baz->getFooBar();
?>

           

trait 屬性

、使用插件的類可以覆寫方法
、不能覆寫屬性
、插件不能定義const 常量
<?php
    trait PropertiesTrait {
        public $same = true;
        public $different = false;
    }

    class PropertiesExample {
        use PropertiesTrait;
        public $same = ; // 嚴厲的标準
        public $different = true; // 緻命錯誤
    }
?>

要使用 trait 屬性(類似于final) 隻能如下

<?php
    trait PropertiesTrait {
        public $same = true;
        public $different = false;
        function asd(){
            echo 'asd<br/>';
        }   
    }

    class PropertiesExample {
        use PropertiesTrait;
        function asd(){
            echo "sss<br/>";
        }
    }
    $o = new PropertiesExample();
    $o->asd();
    var_dump($o->same); // 使用屬性 
?>
           

final 正确的寫法

<?php
    class PropertiesExample {
        // 正确的寫法
        final protected function example() {
        }
        // 錯誤的
        protected final function example222() {
        }
    }
?>