PHP 访问控制

PHP 访问控制


在 PHP 中对属性或方法的访问控制(PHP 7.1.0 以后支持常量),是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。

  • 被定义为公有(public)的类成员可以在任何地方被访问。
  • 被定义为受保护的(protected)类成员则可以被其自身以及其子类和父类访问。
  • 被定义为私有的(private)类成员则只能被其定义所在的类访问。

属性的访问控制

类属性必须定义为公有,受保护,私有之一。如果用 var 定义,则被视为公有。

示例

示例 #1 公有(public)属性

class MyClass
{
    public $public = '迹忆客';

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

$obj = new MyClass();
echo $obj->public; // 这行能被正常执行
$obj->printHello();

上面程序输出

迹忆客
迹忆客

示例 2 保护(protected) 和 私有(private)

class MyClass
{
    public $public = '迹忆客';
    protected $protected = '保护';
    private $private = '私有';

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

$obj = new MyClass();
$obj->printHello(); // 输出 迹忆客、保护 和 私有
echo $obj->public; // 正常执行,输出:迹忆客
echo $obj->protected; // 这行会产生一个致命错误
echo $obj->private; // 这行也会产生一个致命错误

方法的访问控制

类中的方法可以被定义为公有(public),私有(private)或受保护(protected)。如果没有设置这些关键字,则该方法默认为公有。

示例

方法声明

<?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 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.0 开始,类的常量可以定义为公有、私有或受保护。如果没有设置这些关键字,则该常量默认为公有。

示例

<?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'));
?>

以上例程会输出:

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

查看笔记

扫码一下
查看教程更方便