iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
自我挑戰組

後端新手PHP+Laravel筆記系列 第 16

[Day16] 類別(Class) - private, protected, public

訪問控制(可見性)

對屬性或方法的訪問控制(PHP 7.1.0 以後支持常量),通過在前面添加關鍵字 public(公有),protected(受保護)或 private(私有)來實現的。

被定義為公有的類成員可以在任何地方被訪問。被定義為受保護的類成員則可以被其自身以及其子類和父類訪問。被定義為私有的類成員則只能被其定義所在的類訪問。

屬性的訪問控制

1. 屬性聲明

類屬性必須定義為公有,受保護,私有之一。如果用 var 定義,則被視為公有

<?php
/**
 * Define MyClass
 */
class MyClass
{
    public $public = 'Public'; // 公有
    protected $protected = 'Protected'; // 受保護
    private $private = 'Private'; // 私有

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // 這行能被正常執行
echo $obj->protected; // 這行會產生一個致命錯誤
echo $obj->private; // 這行也會產生一個致命錯誤
$obj->printHello(); // 輸出 Public、Protected 和 Private


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // 可以對 public 和 protected 進行重定義,但 private 而不能
    public $public = 'Public2';
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj2->public; // 這行能被正常執行
echo $obj2->protected; // 這行會產生一個致命錯誤
echo $obj2->private; // 未定義 private
$obj2->printHello(); // 輸出 Public2、Protected2 和 Undefined

?>

方法的訪問控制

方法聲明
<?php
/**
 * Define MyClass
 */
class MyClass
{
    // 聲明一個公有的構造函數
    public function __construct() { }

    // 聲明一個公有的方法
    public function MyPublic() { }

    // 聲明一個受保護的方法
    protected function MyProtected() { }

    // 聲明一個私有的方法
    private function MyPrivate() { }

    // 預設為公開方法
    function Foo()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}

$myclass = new MyClass;
$myclass->MyPublic(); // 這行能被正常執行
$myclass->MyProtected(); // 會出現致命錯誤
$myclass->MyPrivate(); // 會出現致命錯誤
$myclass->Foo(); // 公有,受保護,私有都可以執行


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // 為公開的函數
    function Foo2()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate(); // 會發生錯誤
    }
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // 这行能被正常执行
$myclass2->Foo2(); // 公有,受保護,私有不可執行只能在原class裡執行

class Bar 
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }

    public function testPublic() {
        echo "Bar::testPublic\n";
    }
    
    private function testPrivate() {
        echo "Bar::testPrivate\n";
    }
}

class Foo extends Bar 
{
    public function testPublic() {
        echo "Foo::testPublic\n";
    }
    
    private function testPrivate() {
        echo "Foo::testPrivate\n";
    }
}

$myFoo = new foo();
$myFoo->test(); // Bar::testPrivate 
                // Foo::testPublic
?>

常量的控制訪問

php 7.1 up 中常量聲明
<?php
/**
 * Define MyClass
 */
class MyClass
{
    // 公有常量
    public const MY_PUBLIC = 'public';

    // 受保護的常量
    protected const MY_PROTECTED = 'protected';

    // 私有常量
    private const MY_PRIVATE = 'private';

    public function foo()
    {
        echo self::MY_PUBLIC;
        echo self::MY_PROTECTED;
        echo self::MY_PRIVATE;
    }
}

$myclass = new MyClass();
MyClass::MY_PUBLIC; // 這行可以正常執行
MyClass::MY_PROTECTED; // 這行會產生一個致命錯誤
MyClass::MY_PRIVATE; // 這行會產生一個致命錯誤
$myclass->foo(); // 將會輸出:Public Protected Private


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // This is public
    function foo2()
    {
        echo self::MY_PUBLIC;
        echo self::MY_PROTECTED;
        echo self::MY_PRIVATE; // 這行會產生一個致命錯誤
    }
}

$myclass2 = new MyClass2;
echo MyClass2::MY_PUBLIC; // 這行可以正常執行
$myclass2->foo2(); // 將會輸出:Public Protected,MY_PRIVATE 是私有常量,無法輸出
?>

其他對象的訪問控制

訪問同一個對像類型的私有成員

同一個類的對象即使不是同一個實例也可以互相訪問對方的私有與受保護成員。這是由於在這些對象的內部具體實現的細節都是已知的

<?php
class Test
{
    private $foo;

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

    private function bar()
    {
        echo 'Accessed the private method.';
    }

    public function baz(Test $other)
    {
        // We can change the private property:
        $other->foo = 'hello';
        var_dump($other->foo);

        // We can also call the private method:
        $other->bar();
    }
}

$test = new Test('test');

$test->baz(new Test('other'));
?>

// outputs
// string(5) "hello"
// Accessed the private method.

資料來源: https://www.php.net/


上一篇
[Day15]PHP Class 類別02
下一篇
[Day17] static靜態方法
系列文
後端新手PHP+Laravel筆記30

尚未有邦友留言

立即登入留言