公共、私人和保护之间的区别是什么?

时间:2022-06-18 15:51:04

When and why should I use public, private, and protected functions and variables inside a class? What is the difference between them?

何时以及为什么要在类中使用公共、私有和受保护的函数和变量?它们之间的区别是什么?

Examples:

例子:

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

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

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

15 个解决方案

#1


1044  

You use:

你使用:

  • public scope to make that variable/function available from anywhere, other classes and instances of the object.

    公共范围,使该变量/函数可以从任何地方、其他类和对象实例中获得。

  • private scope when you want your variable/function to be visible in its own class only.

    当您希望变量/函数仅在自己的类中可见时,私有范围。

  • protected scope when you want to make your variable/function visible in all classes that extend current class including the parent class.

    当您希望在所有扩展当前类(包括父类)的类中显示变量/函数时,保护范围。

More: (For comprehensive information)

:综合信息()

#2


973  

公共、私人和保护之间的区别是什么?

Public:

When you declare a method (function) or a property (variable) as public, those methods and properties can be accessed by:

当您声明一个方法(函数)或属性(变量)为public时,可以通过以下方法访问这些方法和属性:

  • The same class that declared it.
  • 声明它的类。
  • The classes that inherit the above declared class.
  • 继承上述声明类的类。
  • Any foreign elements outside this class can also access those things.
  • 这个类之外的任何外来元素也可以访问这些东西。

Example:

例子:

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

Protected:

When you declare a method (function) or a property (variable) as protected, those methods and properties can be accessed by

当您声明一个方法(函数)或属性(变量)作为保护时,这些方法和属性可以被访问。

  • The same class that declared it.
  • 声明它的类。
  • The classes that inherit the above declared class.
  • 继承上述声明类的类。

Outsider members cannot access those variables. "Outsiders" in the sense that they are not object instances of the declared class itself.

外部成员不能访问这些变量。“外来者”的意思是,他们不是声明类本身的对象实例。

Example:

例子:

<?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

The exact error will be this:

准确的误差将是:

PHP Fatal error: Cannot access protected property GrandPa::$name

PHP致命错误:无法访问受保护的属性爷爷::$name。


Private:

When you declare a method (function) or a property (variable) as private, those methods and properties can be accessed by:

当您声明一个方法(函数)或属性(变量)为私有时,可以通过以下方法访问这些方法和属性:

  • The same class that declared it.
  • 声明它的类。

Outsider members cannot access those variables. Outsiders in the sense that they are not object instances of the declared class itself and even the classes that inherit the declared class.

外部成员不能访问这些变量。外部人员认为它们不是声明类本身的对象实例,甚至不是继承声明类的类。

Example:

例子:

<?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

The exact error messages will be:

准确的错误消息将是:

Notice: Undefined property: Daddy::$name
Fatal error: Cannot access private property GrandPa::$name

注意:未定义的属性:爸爸:$name致命错误:不能访问私有财产爷爷::$name。


Dissecting the Grandpa Class using Reflection

This subject is not really out of scope, and I'm adding it here just to prove that reflection is really powerful. As I had stated in the above three examples, protected and private members (properties and methods) cannot be accessed outside of the class.

这个主题并没有超出范围,我在这里添加它只是为了证明反射是非常强大的。正如我在上面的三个示例中所述,保护和私有成员(属性和方法)不能在类之外访问。

However, with reflection you can do the extra-ordinary by even accessing protected and private members outside of the class!

然而,有了反射,你甚至可以通过访问在类之外访问受保护和私有的成员来完成额外的任务!

Well, what is reflection?

Reflection adds the ability to reverse-engineer classes, interfaces, functions, methods and extensions. Additionally, they offers ways to retrieve doc comments for functions, classes and methods.

反射增加了反向工程类、接口、函数、方法和扩展的能力。此外,他们还提供了检索功能、类和方法的doc注释的方法。

Preamble

We have a class named Grandpas and say we have three properties. For easy understanding, consider there are three grandpas with names:

我们有一个名为Grandpas的类,我们有三个属性。为了便于理解,可以考虑以下三个名字:

  • Mark Henry
  • 马克亨利
  • John *
  • 约翰冲突
  • Will Jones
  • 将琼斯

Let us make them (assign modifiers) public, protected and private respectively. You know very well that protected and private members cannot be accessed outside the class. Now let's contradict the statement using reflection.

让我们分别让它们(分配修饰符)公有、受保护和私有。您很清楚,保护和私有成员不能在类之外访问。现在让我们用反射来反驳这个说法。

The code

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John *';  // 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>";
}

Output:

输出:

#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 * and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3

Common Misconceptions:

Please do not confuse with the below example. As you can still see, the private and protected members cannot be accessed outside of the class without using reflection

请不要混淆下面的例子。您仍然可以看到,在不使用反射的情况下,私有和受保护的成员不能在类之外访问。

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John *';  // 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);

Output:

输出:

GrandPas Object
(
    [name1] => Mark Henry
    [name2:protected] => John *
    [name3:GrandPas:private] => Will Jones
)

Debugging functions

print_r, var_export and var_dump are debugger functions. They present information about a variable in a human-readable form. These three functions will reveal the protected and private properties of objects with PHP 5. Static class members will not be shown.

print_r、var_export和var_dump是调试器函数。它们以人类可读的形式提供有关变量的信息。这三个函数将显示带有PHP 5的对象的受保护和私有属性。静态类成员将不会显示。


More resources:


#3


77  

It is typically considered good practice to default to the lowest visibility required as this promotes data encapsulation and good interface design. When considering member variable and method visibility think about the role the member plays in the interaction with other objects.

它通常被认为是一种很好的做法,默认为最低的可见性,因为这促进了数据封装和良好的接口设计。当考虑成员变量和方法可视性时,考虑成员在与其他对象交互时所扮演的角色。

If you "code to an interface rather than implementation" then it's usually pretty straightforward to make visibility decisions. In general, variables should be private or protected unless you have a good reason to expose them. Use public accessors (getters/setters) instead to limit and regulate access to a class's internals.

如果您将“代码转换为接口而不是实现”,那么通常很容易做出可见性决策。一般来说,变量应该是私有的或者是受保护的,除非您有充分的理由来公开它们。使用公共访问器(getter /setter)来限制和规范对类内部的访问。

To use a car as an analogy, things like speed, gear, and direction would be private instance variables. You don't want the driver to directly manipulate things like air/fuel ratio. Instead, you expose a limited number of actions as public methods. The interface to a car might include methods such as accelerate(), deccelerate()/brake(), setGear(), turnLeft(), turnRight(), etc.

以汽车为例,速度、齿轮和方向等都是私有的实例变量。你不希望司机直接操纵空气/燃料比。相反,您将有限数量的操作公开为公共方法。汽车的接口可能包括加速(),deccelerate()/制动器(),setGear(), turnLeft(), turnRight(),等等。

The driver doesn't know nor should he care how these actions are implemented by the car's internals, and exposing that functionality could be dangerous to the driver and others on the road. Hence the good practice of designing a public interface and encapsulating the data behind that interface.

司机不知道,也不应该关心这些动作是如何由汽车的内部来实现的,并且暴露这个功能可能对司机和路上的其他人是危险的。因此,设计一个公共接口并封装该接口背后的数据的良好实践。

This approach also allows you to alter and improve the implementation of the public methods in your class without breaking the interface's contract with client code. For example, you could improve the accelerate() method to be more fuel efficient, yet the usage of that method would remain the same; client code would require no changes but still reap the benefits of your efficiency improvement.

这种方法还允许您在不破坏接口与客户端代码的契约的情况下更改和改进您的类中的公共方法的实现。例如,您可以改进加速()方法以提高燃料效率,但该方法的使用将保持不变;客户端代码不需要更改,但仍然可以获得效率改进的好处。

Edit: Since it seems you are still in the midst of learning object oriented concepts (which are much more difficult to master than any language's syntax), I highly recommend picking up a copy of PHP Objects, Patterns, and Practice by Matt Zandstra. This is the book that first taught me how to use OOP effectively, rather than just teaching me the syntax. I had learned the syntax years beforehand, but that was useless without understanding the "why" of OOP.

编辑:因为看起来您仍然处于学习面向对象的概念(这比任何语言的语法都要困难得多),我强烈推荐使用Matt Zandstra的一份PHP对象、模式和实践的副本。这本书教会了我如何有效地使用OOP,而不仅仅是教我语法。我以前学过语法,但是如果不理解OOP的“为什么”,那就没有用了。

#4


67  

private - can be accessed from WITHIN the class only

私有-只能从类中访问。

protected - can be accessed from WITHIN the class and INHERITING classes

保护-可以从类中访问并继承类。

public - can be accessed from code OUTSIDE the class as well

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

This applies to functions as well as variables.

这适用于函数和变量。

#5


23  

The difference is as follows:

差异如下:

Public :: A public variable or method can be accessed directly by any user of the class.

公共::公共变量或方法可以由类的任何用户直接访问。

Protected :: A protected variable or method cannot be accessed by users of the class but can be accessed inside a subclass that inherits from the class.

保护::受保护的变量或方法不能被类的用户访问,但可以在继承自类的子类中访问。

Private :: A private variable or method can only be accessed internally from the class in which it is defined.This means that a private variable or method cannot be called from a child that extends the class.

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

#6


15  

Visibility Scopes with Abstract Examples :: Makes easy Understanding

可见范围与抽象的例子::易于理解。

This visibility of a property or method is defined by pre-fixing declaration of one of three keyword (Public, protected and private)

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

Public : If a property or method is defined as public, it means it can be both access and manipulated by anything that can refer to object.

Public:如果一个属性或方法被定义为Public,它意味着它可以被任何可以引用的对象访问和操作。

  • Abstract eg. Think public visibility scope as "public picnic" that anybody can come to.
  • 文摘。把公众视野当作“公共野餐”,任何人都可以参加。

Protected : when a property or method visibility is set to protected members can only be access within the class itself and by inherited & inheriting classes. (Inherited:- a class can have all the properties and methods of another class).

保护:当属性或方法可见性被设置为受保护成员时,只能在类本身中访问,并且继承和继承类。(继承:-一个类可以拥有另一个类的所有属性和方法)。

  • Think as a protected visibility scope as "Company picnic" where company members and their family members are allowed not the public. It's the most common scope restriction.
  • 以“公司野餐”作为一个受保护的可视范围,公司成员和他们的家庭成员不允许公开。这是最常见的范围限制。

Private : When a property or method visibility is set to private, only the class that has the private members can access those methods and properties(Internally within the class), despite of whatever class relation there maybe.

私有:当属性或方法可见性被设置为私有时,只有拥有私有成员的类才能访问这些方法和属性(在类内部),尽管可能存在任何类关系。

  • with picnic analogy think as a "company picnic where only the company members are allowed" in the picnic. not family neither general public are allowed.
  • 用野餐的比喻来说,这是“公司野餐,只有公司成员才能参加野餐”。家庭和公众都不允许。

#7


13  

/**
 * 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

Extracted From :

http://php.net/manual/en/language.oop5.visibility.php

http://php.net/manual/en/language.oop5.visibility.php

#8


7  

Considering 'when':
I tend to declare everything as private initially, if I'm not exactly sure. Reason being, that it's usually much easier to turn a private method public than the other way round. That's because you can at least be sure that the private method hasn't been used anywhere but in the class itself. A public method may already be in use everywhere, possibly requiring an extensive re-write.

考虑“什么时候”:如果我不确定的话,我倾向于把所有事情都说成是私人的。原因是,将私人方法公开比反过来要容易得多。这是因为您至少可以确信,私有方法在任何地方都没有被使用,而是在类本身中使用。公共方法可能已经在任何地方使用,可能需要广泛的重写。

Update: i go for a default of protected nowadays, because I've come to find that it's good enough for encapsulation and doesn't get in the way when I'm extending classes (which i try to avoid anyway). Only if i have a good reason to use the other two, i will.

更新:我现在默认的是受保护的,因为我发现它对封装来说已经足够好了,并且在我扩展类的时候不会妨碍(我尽量避免)。除非我有充分的理由使用另外两个,我会。

A good reason for a private method would be one that implements something inherent to that object that even an extending class should not change (factual reason, in addition to encapsulation). Eventually, it's still easy enough to track down where a protected method is being used usually, so i default to protected nowadays. Maybe not 100% objective "in the trenches" experience, I admit.

私有方法的一个很好的理由是,它实现了该对象固有的某些东西,即使扩展类也不应该改变(事实原因,除了封装)。最终,它仍然很容易找到一个受保护的方法被使用的地方,所以我现在默认是受保护的。我承认,也许不是百分之百的“战壕”经验。

#9


6  

PHP manual has a good read on the question here.

PHP手册有一个很好的问题。

The visibility of a property or method can be defined by prefixing the declaration with the keywords public, protected or private. Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited and parent classes. Members declared as private may only be accessed by the class that defines the member.

属性或方法的可见性可以通过在公开、受保护或私有的关键字前面来定义。类成员声明public可以在任何地方访问。声明保护的成员只能在类本身和继承和父类中访问。成员声明为私有的成员只能由定义成员的类访问。

#10


6  

⚡️ Here is an easy way to remember the scope of public, protected and private.

⚡️下面是一个简单的方法记住了公众的范围,保护和隐私的。

PUBLIC:

公众:

  • public scope: A public variable/function is available to both objects and other classes.
  • 公共范围:一个公共变量/函数对对象和其他类都可用。

PROTECTED:

保护:

  • protected scope: A protected variable/function is available to all the classes that extend the current class.
  • 受保护的范围:对扩展当前类的所有类都可用受保护的变量/函数。
  • No! Objects cannot access this scope
  • 不!对象无法访问此范围。

PRIVATE:

私人:

  • private scope: A private variable/function is only visible in the current class where it is being defined.
  • 私有范围:私有变量/函数只能在定义它的当前类中可见。
  • No! Class that extend the current class cannot access this scope.
  • 不!扩展当前类的类不能访问此范围。
  • No! Objects cannot access this scope.
  • 不!对象无法访问此范围。

Read the Visibility of a method or variable on PHP Manual.

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

#11


5  

For me, this is the most useful way to understand the three property types:

对我来说,这是理解这三种属性最有效的方式:

Public: Use this when you are OK with this variable being directly accessed and changed from anywhere in your code.

Public:当您可以使用这个变量时,可以在代码中的任何地方直接访问和更改这个变量。

Example usage from outside of the class:

课堂外的范例用法:

$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;

Protected: Use this when you want to force other programmers (and yourself) to use getters/setters outside of the class when accessing and setting variables (but you should be consistent and use the getters and setters inside the class as well). This or private tend to be the default way you should set up all class properties.

保护:当您想要强制其他程序员(和您自己)在访问和设置变量时使用getters/setters(但是您应该保持一致,并且在类中使用getter和setter)时,请使用它。这或私有倾向是默认的方式,您应该设置所有类属性。

Why? Because if you decide at some point in the future (maybe even in like 5 minutes) that you want to manipulate the value that is returned for that property or do something with it before getting/setting, you can do that without refactoring everywhere you have used it in your project.

为什么?因为如果你在将来某一时刻决定(甚至可能在5分钟内),你想要操纵那个属性返回的值,或者在获取/设置之前对它做一些事情,你可以在没有重构的情况下,在你的项目中使用它。

Example usage from outside of the class:

课堂外的范例用法:

$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();

Private: private properties are very similar to protected properties. But the distinguishing feature/difference is that making it private also makes it inaccessible to child classes without using the parent class's getter or setter.

私有属性:私有属性非常类似于受保护的属性。但是区别的特性/区别是,使它私有也使得它不能使用父类的getter或setter来访问子类。

So basically, if you are using getters and setters for a property (or if it is used only internally by the parent class and it isn't meant to be accessible anywhere else) you might as well make it private, just to prevent anyone from trying to use it directly and introducing bugs.

基本上,如果您正在使用getter和setter属性(或者如果它是由父类仅在内部使用,它不是要访问其他地方)你不妨让它私有的,只是为了防止任何人试图使用它直接和引入bug。

Example usage inside a child class (that extends MyObject):

子类中的示例用法(扩展MyObject):

$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();

#12


4  

They're there to allow for different levels of encapsulation

它们允许不同级别的封装。

#13


4  

Variables in PHP are cast in three different type:

PHP中的变量有三种类型:

Public : values of this variable types are available in all scope and call on execution of you code. declare as: public $examTimeTable;

Public:此变量类型的值在所有范围内都可用,并调用执行代码。声明:公共examTimeTable美元;

Private: Values of this type of variable are only available on only to the class it belongs to. private $classRoomComputers;

私有:此类变量的值只在它所属的类上可用。私人classRoomComputers美元;

Protected: Values of this class only and only available when Access been granted in a form of inheritance or their child class. generally used :: to grant access by parent class

保护:该类的值仅当以继承或子类的形式授予访问时才可用。通常使用::授予父类的访问权。

protected $familyWealth;

保护familyWealth美元;

#14


3  

Reviving an old question, but I think a really good way to think of this is in terms of the API that you are defining.

恢复一个老问题,但是我认为一个很好的方法来思考这个问题是在你定义的API方面。

  • public - Everything marked public is part of the API that anyone using your class/interface/other will use and rely on.

    public -所有标记为public的东西都是API的一部分,任何人使用您的类/接口/其他工具都将使用并依赖它。

  • protected - Don't be fooled, this is also part of the API! People can subclass, extend your code and use anything marked protected.

    保护-不要被愚弄,这也是API的一部分!人们可以子类化,扩展您的代码并使用任何有标记的保护。

  • private - Private properties and methods can be changed as much as you like. No one else can use these. These are the only things you can change without making breaking changes.

    私有属性和方法可以随意更改。没有其他人可以使用这些。这些是你唯一可以改变而不改变的东西。

Or in Semver terms:

或Semver术语:

  • Changes to anything public or protected should be considered MAJOR changes.

    任何公共或受保护的更改都应该被视为重大的变化。

  • Anything new public or protected should be (at least) MINOR

    任何新的公共或受保护的东西都应该是(至少)小的。

  • Only new/changes to anything private can be PATCH

    只有新的/改变到任何私有的可以是补丁。

So in terms of maintaining code, its good to be careful about what things you make public or protected because these are the things you are promising to your users.

因此,在维护代码方面,最好注意哪些东西是公共的,哪些是受保护的,因为这些是你向用户承诺的东西。

#15


1  

Public: is a default state when you declare a variable or method, can be accessed by anything directly to the object.

Public:当您声明一个变量或方法时,它是一个默认状态,可以通过任何直接访问对象的方式访问。

Protected: Can be accessed only within the object and subclasses.

保护:只能在对象和子类中访问。

Private: Can be referenced only within the object, not subclasses.

私有:只能在对象中引用,而不是子类。

#1


1044  

You use:

你使用:

  • public scope to make that variable/function available from anywhere, other classes and instances of the object.

    公共范围,使该变量/函数可以从任何地方、其他类和对象实例中获得。

  • private scope when you want your variable/function to be visible in its own class only.

    当您希望变量/函数仅在自己的类中可见时,私有范围。

  • protected scope when you want to make your variable/function visible in all classes that extend current class including the parent class.

    当您希望在所有扩展当前类(包括父类)的类中显示变量/函数时,保护范围。

More: (For comprehensive information)

:综合信息()

#2


973  

公共、私人和保护之间的区别是什么?

Public:

When you declare a method (function) or a property (variable) as public, those methods and properties can be accessed by:

当您声明一个方法(函数)或属性(变量)为public时,可以通过以下方法访问这些方法和属性:

  • The same class that declared it.
  • 声明它的类。
  • The classes that inherit the above declared class.
  • 继承上述声明类的类。
  • Any foreign elements outside this class can also access those things.
  • 这个类之外的任何外来元素也可以访问这些东西。

Example:

例子:

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

Protected:

When you declare a method (function) or a property (variable) as protected, those methods and properties can be accessed by

当您声明一个方法(函数)或属性(变量)作为保护时,这些方法和属性可以被访问。

  • The same class that declared it.
  • 声明它的类。
  • The classes that inherit the above declared class.
  • 继承上述声明类的类。

Outsider members cannot access those variables. "Outsiders" in the sense that they are not object instances of the declared class itself.

外部成员不能访问这些变量。“外来者”的意思是,他们不是声明类本身的对象实例。

Example:

例子:

<?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

The exact error will be this:

准确的误差将是:

PHP Fatal error: Cannot access protected property GrandPa::$name

PHP致命错误:无法访问受保护的属性爷爷::$name。


Private:

When you declare a method (function) or a property (variable) as private, those methods and properties can be accessed by:

当您声明一个方法(函数)或属性(变量)为私有时,可以通过以下方法访问这些方法和属性:

  • The same class that declared it.
  • 声明它的类。

Outsider members cannot access those variables. Outsiders in the sense that they are not object instances of the declared class itself and even the classes that inherit the declared class.

外部成员不能访问这些变量。外部人员认为它们不是声明类本身的对象实例,甚至不是继承声明类的类。

Example:

例子:

<?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

The exact error messages will be:

准确的错误消息将是:

Notice: Undefined property: Daddy::$name
Fatal error: Cannot access private property GrandPa::$name

注意:未定义的属性:爸爸:$name致命错误:不能访问私有财产爷爷::$name。


Dissecting the Grandpa Class using Reflection

This subject is not really out of scope, and I'm adding it here just to prove that reflection is really powerful. As I had stated in the above three examples, protected and private members (properties and methods) cannot be accessed outside of the class.

这个主题并没有超出范围,我在这里添加它只是为了证明反射是非常强大的。正如我在上面的三个示例中所述,保护和私有成员(属性和方法)不能在类之外访问。

However, with reflection you can do the extra-ordinary by even accessing protected and private members outside of the class!

然而,有了反射,你甚至可以通过访问在类之外访问受保护和私有的成员来完成额外的任务!

Well, what is reflection?

Reflection adds the ability to reverse-engineer classes, interfaces, functions, methods and extensions. Additionally, they offers ways to retrieve doc comments for functions, classes and methods.

反射增加了反向工程类、接口、函数、方法和扩展的能力。此外,他们还提供了检索功能、类和方法的doc注释的方法。

Preamble

We have a class named Grandpas and say we have three properties. For easy understanding, consider there are three grandpas with names:

我们有一个名为Grandpas的类,我们有三个属性。为了便于理解,可以考虑以下三个名字:

  • Mark Henry
  • 马克亨利
  • John *
  • 约翰冲突
  • Will Jones
  • 将琼斯

Let us make them (assign modifiers) public, protected and private respectively. You know very well that protected and private members cannot be accessed outside the class. Now let's contradict the statement using reflection.

让我们分别让它们(分配修饰符)公有、受保护和私有。您很清楚,保护和私有成员不能在类之外访问。现在让我们用反射来反驳这个说法。

The code

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John *';  // 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>";
}

Output:

输出:

#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 * and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3

Common Misconceptions:

Please do not confuse with the below example. As you can still see, the private and protected members cannot be accessed outside of the class without using reflection

请不要混淆下面的例子。您仍然可以看到,在不使用反射的情况下,私有和受保护的成员不能在类之外访问。

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John *';  // 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);

Output:

输出:

GrandPas Object
(
    [name1] => Mark Henry
    [name2:protected] => John *
    [name3:GrandPas:private] => Will Jones
)

Debugging functions

print_r, var_export and var_dump are debugger functions. They present information about a variable in a human-readable form. These three functions will reveal the protected and private properties of objects with PHP 5. Static class members will not be shown.

print_r、var_export和var_dump是调试器函数。它们以人类可读的形式提供有关变量的信息。这三个函数将显示带有PHP 5的对象的受保护和私有属性。静态类成员将不会显示。


More resources:


#3


77  

It is typically considered good practice to default to the lowest visibility required as this promotes data encapsulation and good interface design. When considering member variable and method visibility think about the role the member plays in the interaction with other objects.

它通常被认为是一种很好的做法,默认为最低的可见性,因为这促进了数据封装和良好的接口设计。当考虑成员变量和方法可视性时,考虑成员在与其他对象交互时所扮演的角色。

If you "code to an interface rather than implementation" then it's usually pretty straightforward to make visibility decisions. In general, variables should be private or protected unless you have a good reason to expose them. Use public accessors (getters/setters) instead to limit and regulate access to a class's internals.

如果您将“代码转换为接口而不是实现”,那么通常很容易做出可见性决策。一般来说,变量应该是私有的或者是受保护的,除非您有充分的理由来公开它们。使用公共访问器(getter /setter)来限制和规范对类内部的访问。

To use a car as an analogy, things like speed, gear, and direction would be private instance variables. You don't want the driver to directly manipulate things like air/fuel ratio. Instead, you expose a limited number of actions as public methods. The interface to a car might include methods such as accelerate(), deccelerate()/brake(), setGear(), turnLeft(), turnRight(), etc.

以汽车为例,速度、齿轮和方向等都是私有的实例变量。你不希望司机直接操纵空气/燃料比。相反,您将有限数量的操作公开为公共方法。汽车的接口可能包括加速(),deccelerate()/制动器(),setGear(), turnLeft(), turnRight(),等等。

The driver doesn't know nor should he care how these actions are implemented by the car's internals, and exposing that functionality could be dangerous to the driver and others on the road. Hence the good practice of designing a public interface and encapsulating the data behind that interface.

司机不知道,也不应该关心这些动作是如何由汽车的内部来实现的,并且暴露这个功能可能对司机和路上的其他人是危险的。因此,设计一个公共接口并封装该接口背后的数据的良好实践。

This approach also allows you to alter and improve the implementation of the public methods in your class without breaking the interface's contract with client code. For example, you could improve the accelerate() method to be more fuel efficient, yet the usage of that method would remain the same; client code would require no changes but still reap the benefits of your efficiency improvement.

这种方法还允许您在不破坏接口与客户端代码的契约的情况下更改和改进您的类中的公共方法的实现。例如,您可以改进加速()方法以提高燃料效率,但该方法的使用将保持不变;客户端代码不需要更改,但仍然可以获得效率改进的好处。

Edit: Since it seems you are still in the midst of learning object oriented concepts (which are much more difficult to master than any language's syntax), I highly recommend picking up a copy of PHP Objects, Patterns, and Practice by Matt Zandstra. This is the book that first taught me how to use OOP effectively, rather than just teaching me the syntax. I had learned the syntax years beforehand, but that was useless without understanding the "why" of OOP.

编辑:因为看起来您仍然处于学习面向对象的概念(这比任何语言的语法都要困难得多),我强烈推荐使用Matt Zandstra的一份PHP对象、模式和实践的副本。这本书教会了我如何有效地使用OOP,而不仅仅是教我语法。我以前学过语法,但是如果不理解OOP的“为什么”,那就没有用了。

#4


67  

private - can be accessed from WITHIN the class only

私有-只能从类中访问。

protected - can be accessed from WITHIN the class and INHERITING classes

保护-可以从类中访问并继承类。

public - can be accessed from code OUTSIDE the class as well

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

This applies to functions as well as variables.

这适用于函数和变量。

#5


23  

The difference is as follows:

差异如下:

Public :: A public variable or method can be accessed directly by any user of the class.

公共::公共变量或方法可以由类的任何用户直接访问。

Protected :: A protected variable or method cannot be accessed by users of the class but can be accessed inside a subclass that inherits from the class.

保护::受保护的变量或方法不能被类的用户访问,但可以在继承自类的子类中访问。

Private :: A private variable or method can only be accessed internally from the class in which it is defined.This means that a private variable or method cannot be called from a child that extends the class.

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

#6


15  

Visibility Scopes with Abstract Examples :: Makes easy Understanding

可见范围与抽象的例子::易于理解。

This visibility of a property or method is defined by pre-fixing declaration of one of three keyword (Public, protected and private)

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

Public : If a property or method is defined as public, it means it can be both access and manipulated by anything that can refer to object.

Public:如果一个属性或方法被定义为Public,它意味着它可以被任何可以引用的对象访问和操作。

  • Abstract eg. Think public visibility scope as "public picnic" that anybody can come to.
  • 文摘。把公众视野当作“公共野餐”,任何人都可以参加。

Protected : when a property or method visibility is set to protected members can only be access within the class itself and by inherited & inheriting classes. (Inherited:- a class can have all the properties and methods of another class).

保护:当属性或方法可见性被设置为受保护成员时,只能在类本身中访问,并且继承和继承类。(继承:-一个类可以拥有另一个类的所有属性和方法)。

  • Think as a protected visibility scope as "Company picnic" where company members and their family members are allowed not the public. It's the most common scope restriction.
  • 以“公司野餐”作为一个受保护的可视范围,公司成员和他们的家庭成员不允许公开。这是最常见的范围限制。

Private : When a property or method visibility is set to private, only the class that has the private members can access those methods and properties(Internally within the class), despite of whatever class relation there maybe.

私有:当属性或方法可见性被设置为私有时,只有拥有私有成员的类才能访问这些方法和属性(在类内部),尽管可能存在任何类关系。

  • with picnic analogy think as a "company picnic where only the company members are allowed" in the picnic. not family neither general public are allowed.
  • 用野餐的比喻来说,这是“公司野餐,只有公司成员才能参加野餐”。家庭和公众都不允许。

#7


13  

/**
 * 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

Extracted From :

http://php.net/manual/en/language.oop5.visibility.php

http://php.net/manual/en/language.oop5.visibility.php

#8


7  

Considering 'when':
I tend to declare everything as private initially, if I'm not exactly sure. Reason being, that it's usually much easier to turn a private method public than the other way round. That's because you can at least be sure that the private method hasn't been used anywhere but in the class itself. A public method may already be in use everywhere, possibly requiring an extensive re-write.

考虑“什么时候”:如果我不确定的话,我倾向于把所有事情都说成是私人的。原因是,将私人方法公开比反过来要容易得多。这是因为您至少可以确信,私有方法在任何地方都没有被使用,而是在类本身中使用。公共方法可能已经在任何地方使用,可能需要广泛的重写。

Update: i go for a default of protected nowadays, because I've come to find that it's good enough for encapsulation and doesn't get in the way when I'm extending classes (which i try to avoid anyway). Only if i have a good reason to use the other two, i will.

更新:我现在默认的是受保护的,因为我发现它对封装来说已经足够好了,并且在我扩展类的时候不会妨碍(我尽量避免)。除非我有充分的理由使用另外两个,我会。

A good reason for a private method would be one that implements something inherent to that object that even an extending class should not change (factual reason, in addition to encapsulation). Eventually, it's still easy enough to track down where a protected method is being used usually, so i default to protected nowadays. Maybe not 100% objective "in the trenches" experience, I admit.

私有方法的一个很好的理由是,它实现了该对象固有的某些东西,即使扩展类也不应该改变(事实原因,除了封装)。最终,它仍然很容易找到一个受保护的方法被使用的地方,所以我现在默认是受保护的。我承认,也许不是百分之百的“战壕”经验。

#9


6  

PHP manual has a good read on the question here.

PHP手册有一个很好的问题。

The visibility of a property or method can be defined by prefixing the declaration with the keywords public, protected or private. Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited and parent classes. Members declared as private may only be accessed by the class that defines the member.

属性或方法的可见性可以通过在公开、受保护或私有的关键字前面来定义。类成员声明public可以在任何地方访问。声明保护的成员只能在类本身和继承和父类中访问。成员声明为私有的成员只能由定义成员的类访问。

#10


6  

⚡️ Here is an easy way to remember the scope of public, protected and private.

⚡️下面是一个简单的方法记住了公众的范围,保护和隐私的。

PUBLIC:

公众:

  • public scope: A public variable/function is available to both objects and other classes.
  • 公共范围:一个公共变量/函数对对象和其他类都可用。

PROTECTED:

保护:

  • protected scope: A protected variable/function is available to all the classes that extend the current class.
  • 受保护的范围:对扩展当前类的所有类都可用受保护的变量/函数。
  • No! Objects cannot access this scope
  • 不!对象无法访问此范围。

PRIVATE:

私人:

  • private scope: A private variable/function is only visible in the current class where it is being defined.
  • 私有范围:私有变量/函数只能在定义它的当前类中可见。
  • No! Class that extend the current class cannot access this scope.
  • 不!扩展当前类的类不能访问此范围。
  • No! Objects cannot access this scope.
  • 不!对象无法访问此范围。

Read the Visibility of a method or variable on PHP Manual.

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

#11


5  

For me, this is the most useful way to understand the three property types:

对我来说,这是理解这三种属性最有效的方式:

Public: Use this when you are OK with this variable being directly accessed and changed from anywhere in your code.

Public:当您可以使用这个变量时,可以在代码中的任何地方直接访问和更改这个变量。

Example usage from outside of the class:

课堂外的范例用法:

$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;

Protected: Use this when you want to force other programmers (and yourself) to use getters/setters outside of the class when accessing and setting variables (but you should be consistent and use the getters and setters inside the class as well). This or private tend to be the default way you should set up all class properties.

保护:当您想要强制其他程序员(和您自己)在访问和设置变量时使用getters/setters(但是您应该保持一致,并且在类中使用getter和setter)时,请使用它。这或私有倾向是默认的方式,您应该设置所有类属性。

Why? Because if you decide at some point in the future (maybe even in like 5 minutes) that you want to manipulate the value that is returned for that property or do something with it before getting/setting, you can do that without refactoring everywhere you have used it in your project.

为什么?因为如果你在将来某一时刻决定(甚至可能在5分钟内),你想要操纵那个属性返回的值,或者在获取/设置之前对它做一些事情,你可以在没有重构的情况下,在你的项目中使用它。

Example usage from outside of the class:

课堂外的范例用法:

$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();

Private: private properties are very similar to protected properties. But the distinguishing feature/difference is that making it private also makes it inaccessible to child classes without using the parent class's getter or setter.

私有属性:私有属性非常类似于受保护的属性。但是区别的特性/区别是,使它私有也使得它不能使用父类的getter或setter来访问子类。

So basically, if you are using getters and setters for a property (or if it is used only internally by the parent class and it isn't meant to be accessible anywhere else) you might as well make it private, just to prevent anyone from trying to use it directly and introducing bugs.

基本上,如果您正在使用getter和setter属性(或者如果它是由父类仅在内部使用,它不是要访问其他地方)你不妨让它私有的,只是为了防止任何人试图使用它直接和引入bug。

Example usage inside a child class (that extends MyObject):

子类中的示例用法(扩展MyObject):

$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();

#12


4  

They're there to allow for different levels of encapsulation

它们允许不同级别的封装。

#13


4  

Variables in PHP are cast in three different type:

PHP中的变量有三种类型:

Public : values of this variable types are available in all scope and call on execution of you code. declare as: public $examTimeTable;

Public:此变量类型的值在所有范围内都可用,并调用执行代码。声明:公共examTimeTable美元;

Private: Values of this type of variable are only available on only to the class it belongs to. private $classRoomComputers;

私有:此类变量的值只在它所属的类上可用。私人classRoomComputers美元;

Protected: Values of this class only and only available when Access been granted in a form of inheritance or their child class. generally used :: to grant access by parent class

保护:该类的值仅当以继承或子类的形式授予访问时才可用。通常使用::授予父类的访问权。

protected $familyWealth;

保护familyWealth美元;

#14


3  

Reviving an old question, but I think a really good way to think of this is in terms of the API that you are defining.

恢复一个老问题,但是我认为一个很好的方法来思考这个问题是在你定义的API方面。

  • public - Everything marked public is part of the API that anyone using your class/interface/other will use and rely on.

    public -所有标记为public的东西都是API的一部分,任何人使用您的类/接口/其他工具都将使用并依赖它。

  • protected - Don't be fooled, this is also part of the API! People can subclass, extend your code and use anything marked protected.

    保护-不要被愚弄,这也是API的一部分!人们可以子类化,扩展您的代码并使用任何有标记的保护。

  • private - Private properties and methods can be changed as much as you like. No one else can use these. These are the only things you can change without making breaking changes.

    私有属性和方法可以随意更改。没有其他人可以使用这些。这些是你唯一可以改变而不改变的东西。

Or in Semver terms:

或Semver术语:

  • Changes to anything public or protected should be considered MAJOR changes.

    任何公共或受保护的更改都应该被视为重大的变化。

  • Anything new public or protected should be (at least) MINOR

    任何新的公共或受保护的东西都应该是(至少)小的。

  • Only new/changes to anything private can be PATCH

    只有新的/改变到任何私有的可以是补丁。

So in terms of maintaining code, its good to be careful about what things you make public or protected because these are the things you are promising to your users.

因此,在维护代码方面,最好注意哪些东西是公共的,哪些是受保护的,因为这些是你向用户承诺的东西。

#15


1  

Public: is a default state when you declare a variable or method, can be accessed by anything directly to the object.

Public:当您声明一个变量或方法时,它是一个默认状态,可以通过任何直接访问对象的方式访问。

Protected: Can be accessed only within the object and subclasses.

保护:只能在对象和子类中访问。

Private: Can be referenced only within the object, not subclasses.

私有:只能在对象中引用,而不是子类。