访问控制
对属性或方法的访问控制,是通过在前面添加关键字 public
(公有), protected
(受保护)或 private
(私有)来实现的。被定义为公有的类成员可以在任何地方被访问。被定义为受保护的类成员则可以被其自身以及其子类和父类访问。被定义为私有的类成员则只能被其定义所在的类访问。
<?php
class Foo
{
/**
* Public property.
*
* @var string
*/
public string $public = 'public';
/**
* Protected property.
*
* @var string
*/
protected string $protected = 'protected';
/**
* Private property.
*
* @var string
*/
private string $private = 'private';
/**
* Return all visibility properties.
*
* @param void
* @return array
*/
public function method(): array
{
return [
'public' => $this->public,
'protected' => $this->protected,
'private' => $this->private
];
}
}
$foo = new Foo();
var_dump($foo->public); // string(6) "public"
var_dump($foo->protected); // PHP Fatal error: Uncaught Error: Cannot access protected property Foo::$protected.
var_dump($foo->private); // PHP Fatal error: Uncaught Error: Cannot access private property Foo::$private.
var_dump($foo->method()); // array(3) { ["public"]=> string(6) "public" ["protected"]=> string(9) "protected" ["private"]=> string(7) "private" }
可以对 public
属性和 protected
属性进行覆盖,但 private
属性不能。
<?php
class Foo
{
/**
* Public property.
*
* @var string
*/
public string $public = 'public';
/**
* Protected property.
*
* @var string
*/
protected string $protected = 'protected';
/**
* Private property.
*
* @var string
*/
private $private = 'private';
}
class Bar extends Foo
{
/**
* Override the parent property.
*
* @var string
*/
protected string $protected = 'bar';
/**
* Return all visibility properties.
*
* @param void
* @return array
*/
public function method(): array
{
return [
'public' => $this->public,
'protected' => $this->protected,
'private' => $this->private
];
}
}
$bar = new Bar();
var_dump($bar->public); // string(6) "public"
var_dump($bar->protected); // PHP Fatal error: Uncaught Error: Cannot access protected property Bar::$protected.
var_dump($bar->private); // NULL
var_dump($bar->method()); // array(3) { ["public"]=> string(6) "public" ["protected"]=> string(3) "bar" ["private"]=> NULL }
类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有。
<?php
class Foo
{
/**
* Public method.
*
* @param void
* @return string
*/
public function public(): string
{
return 'public';
}
/**
* Protected method.
*
* @param void
* @return string
*/
protected function protected(): string
{
return 'protected';
}
/**
* Private method.
*
* @param void
* @return string
*/
private function private(): string
{
return 'private';
}
/**
* Call all visibility methods.
*
* @param void
* @return array
*/
public function method(): array
{
return [
'public' => $this->public(),
'protected' => $this->protected(),
'private' => $this->private()
];
}
}
$foo = new Foo();
var_dump($foo->public()); // string(6) "public"
var_dump($foo->protected()); // PHP Fatal error: Uncaught Error: Call to protected method Foo::protected() from context ''.
var_dump($foo->private()); // PHP Fatal error: Uncaught Error: Call to private method Foo::private() from context ''.
var_dump($foo->method()); // array(3) { ["public"]=> string(6) "public" ["protected"]=> string(9) "protected" ["private"]=> string(7) "private" }
可以对 public
方法和 protected
方法进行覆盖,但 private
方法不能。
<?php
class Foo
{
/**
* Public method.
*
* @param void
* @return string
*/
public function public(): string
{
return 'public';
}
/**
* Protected method.
*
* @param void
* @return string
*/
protected function protected(): string
{
return 'protected';
}
/**
* Private method.
*
* @param void
* @return string
*/
private function private(): string
{
return 'private';
}
}
class Bar extends Foo
{
/**
* Override the parent method.
*
* @param void
* @return string
*/
protected function protected(): string
{
return 'bar';
}
/**
* Call all visibility methods.
*
* @param void
* @return array
*/
public function method(): array
{
return [
'public' => $this->public(),
'protected' => $this->protected(),
'private' => $this->private()
];
}
}
$bar = new Bar();
var_dump($bar->public()); // string(6) "public"
var_dump($bar->protected()); // PHP Fatal error: Uncaught Error: Call to protected method Bar::protected() from context ''.
var_dump($bar->private()); // PHP Fatal error: Uncaught Error: Call to private method Foo::private() from context ''.
var_dump($bar->method()); // PHP Fatal error: Uncaught Error: Call to private method Foo::private() from context 'Bar'.
更多的例子。
<?php
class Foo
{
/**
* Public method.
*
* @param void
* @return string
*/
public function public(): string
{
return 'Foo::public';
}
/**
* Private method.
*
* @param void
* @return string
*/
private function private(): string
{
return 'Foo::private';
}
/**
* Just a test method.
*
* @param void
* @return void
*/
public function method()
{
var_dump($this->public());
var_dump($this->private());
}
}
class Bar extends Foo
{
/**
* Override the parent method.
*
* @param void
* @return string
*/
public function public(): string
{
return 'Bar::public';
}
/**
* Private method.
*
* @param void
* @return string
*/
private function private(): string
{
return 'Bar::private';
}
}
$bar = new Bar();
$bar->method();
// string(11) "Bar::public"
// string(12) "Foo::private"
同一个类的对象即使不是同一个实例也可以互相访问对方的私有与受保护成员。这是由于在这些对象的内部具体实现的细节都是已知的。
<?php
class Foo
{
/**
* Private property.
*
* @var string
*/
private string $property;
/**
* Initialize the value of the property.
*
* @param string $value
* @return void
*/
public function __construct(string $value)
{
$this->property = $value;
}
/**
* Change the specified property of the specified class.
*
* @param Foo $instance
* @return string
*/
public function method(Foo $instance): string
{
return $instance->property = 'bar';
}
}
$foo = new Foo('foo');
var_dump($foo->method(new Foo('bar'))); // string(3) "bar"