公共,私有和受保护的有什么区别?

什么时候以及为什么应该在类中使用publicprivateprotected函数和变量?它们之间有什么区别?

例子:

// Public
public $variable;
public function doSomething() {
  // ...
}

// Private
private $variable;
private function doSomething() {
  // ...
}

// Protected
protected $variable;
protected function doSomething() {
  // ...
}

答案

你用:

  • public范围,以使该属性 / 方法可从任何位置,对象的其他类和实例使用。

  • 当您只希望您的属性 / 方法在其自己的类中可见时,请使用private范围。

  • 当您想使您的属性 / 方法在扩展当前类的所有类(包括父类)中可见时,请使用protected范围。

更多:(有关全面信息)

<?php

class GrandPa
{
    public $name='Mark Henry';  // A public variable
}

class Daddy extends GrandPa // Inherited class
{
    function displayGrandPaName()
    {
        return $this->name; // The public variable will be available to the inherited class
    }

}

// Inherited class Daddy wants to know Grandpas Name
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'

// Public variables can also be accessed outside of the class!
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'
<?php

class GrandPa
{
    protected $name = 'Mark Henry';
}

class Daddy extends GrandPa
{
    function displayGrandPaName()
    {
        return $this->name;
    }

}

$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'

$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
<?php

class GrandPa
{
    private $name = 'Mark Henry';
}

class Daddy extends GrandPa
{
    function displayGrandPaName()
    {
        return $this->name;
    }

}

$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Results in a Notice 

$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected  modifier
    private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
}


# Scenario 1: without reflection
$granpaWithoutReflection = new GrandPas;

# Normal looping to print all the members of this class
echo "#Scenario 1: Without reflection<br>";
echo "Printing members the usual way.. (without reflection)<br>";
foreach($granpaWithoutReflection as $k=>$v)
{
    echo "The name of grandpa is $v and he resides in the variable $k<br>";
}

echo "<br>";

#Scenario 2: Using reflection

$granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
$granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)


echo "#Scenario 2: With reflection<br>";
echo "Printing members the 'reflect' way..<br>";

foreach($granpaNames as $k=>$v)
{
    echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
#Scenario 1: Without reflection
Printing members the usual way.. (Without reflection)
The name of grandpa is Mark Henry and he resides in the variable name1

#Scenario 2: With reflection
Printing members the 'reflect' way..
The name of grandpa is Mark Henry and he resides in the variable name1
The name of grandpa is John Clash and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3
<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected modifier
    private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
}

$granpaWithoutReflections = new GrandPas;
print_r($granpaWithoutReflections);
GrandPas Object
(
    [name1] => Mark Henry
    [name2:protected] => John Clash
    [name3:GrandPas:private] => Will Jones
)

这种方法还允许您更改和改进类中公共方法的实现,而不会破坏与客户端代码的接口约定。例如,您可以改进accelerate()方法以提高燃料效率,但该方法的用法将保持不变;客户端代码无需进行任何更改,但仍可从效率提高中获得收益。

编辑:由于您似乎仍在学习面向对象的概念(比任何一种语言的语法都难于掌握),所以我强烈建议您阅读 Matt Zandstra 撰写的《 PHP 对象,模式和实践》 。这是第一本书,教我如何有效地使用 OOP,而不仅仅是教我语法。我之前已经学过语法,但是如果不了解 OOP 的 “原因”,那将毫无用处。

private - 只能从 WITHIN 类中访问

protected - 可以从 WITHIN 类和 INHERITING 类访问

public - 可以从代码之外的类也可以访问

这适用于函数以及变量。

区别如下:

Public :: 该类的任何用户都可以直接访问 public 变量或方法。

Protected :: 受保护的变量或方法不能由该类的用户访问,但可以在从该类继承的子类内部访问。

Private :: 私有变量或方法只能从定义它的类内部访问,这意味着不能从扩展该类的子级调用私有变量或方法。

具有抽象示例的 可见性范围 :: 易于理解

属性或方法的这种可见性由三个关键字(公共,保护和私有)之一的前缀声明定义。

Public :如果将属性或方法定义为 public,则意味着可以由任何引用对象的对象访问和操纵它。

  • 摘要例如将公众可见度范围视为任何人都可以参加的“公众野餐”

受保护的:将属性或方法的可见性设置为受保护的成员时,只能在类本身内以及通过继承和继承的类访问。 (继承:- 一个类可以具有另一个类的所有属性和方法)。

/**
 * 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; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // We can redeclare the public and protected method, but not private
    protected $protected = 'Protected2';

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

$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined

⚡️这是一种记住publicprotectedprivate范围的简单方法。

PUBLIC

  • public范围:公共变量 / 函数可用于对象和其他类。

PROTECTED

  • protected范围:受保护的变量 / 函数可用于扩展当前类的所有类。
  • 没有!对象无法访问此范围

PRIVATE

  • private范围:私有变量 / 函数仅在定义它的当前类中可见。
  • 没有!扩展当前类的类无法访问此范围。
  • 没有!对象无法访问此范围。

阅读 PHP 手册上的方法或变量的可见性

考虑 “ 何时 ”:
如果不确定,我一开始会倾向于将所有内容都声明为私有。原因是,公开私有方法通常比其他方法容易得多。那是因为您至少可以确保私有方法没有在类本身之外的任何地方使用。公共方法可能已在各处使用,可能需要大量重写。

更新 :我现在使用默认的protected ,因为我发现它对于封装已经足够好了,并且在扩展类时也没有碍事(无论如何,我都会设法避免这种情况)。只有当我有充分的理由使用其他两个时,我才会这样做。

使用private方法的一个好理由是实现该对象固有的某些东西,即使扩展类也不应更改(事实原因,除了封装,例如内部状态管理)。最终,仍然很容易找到通常在什么地方使用protected方法,因此我现在默认为protected 。我承认,也许不是 100%客观的 “在战 trench 中” 的经历。

PHP 手册对这里的问题有很好的阅读。

属性或方法的可见性可以通过在声明的前面加上关键字 public,protected 或 private 来定义。宣告为公开的班级成员可以在任何地方访问。声明为 protected 的成员只能在该类内部以及继承的和父类访问。声明为私有的成员只能由定义该成员的类访问。