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

时间:2021-01-21 15:48:47

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

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

Examples:

例子:

// Publicpublic $variable;public function doSomething() {  // ...}// Privateprivate $variable;private function doSomething() {  // ...}// Protectedprotected $variable;protected function doSomething() {  // ...}

16 个解决方案

#1


1060  

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


997  

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

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:

例子:

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

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

  • 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:

例子:

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

例子:

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

注意:未定义属性:Daddy: $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

<?phpclass 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 classecho "#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 reflectionPrinting members the usual way.. (Without reflection)The name of grandpa is Mark Henry and he resides in the variable name1#Scenario 2: With reflectionPrinting members the 'reflect' way..The name of grandpa is Mark Henry and he resides in the variable name1The name of grandpa is John * and he resides in the variable name2The 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

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

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


78  

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()/brake()、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


68  

private - can be accessed from WITHIN the class only

private -只能从类内部访问

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.

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

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、protected和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.

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

  • 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


14  

/** * 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; // Worksecho $obj->protected; // Fatal Errorecho $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; // Worksecho $obj2->private; // Undefinedecho $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


8  

⚡️ 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手册中方法或变量的可见性。

#9


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.

更新:我现在使用的是protected的默认值,因为我发现它对于封装已经足够好了,并且在扩展类的时候不会受到影响(无论如何我都尽量避免这种情况)。只有当我有充分的理由使用另外两个时,我才会使用。

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.

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

#10


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、protected或private来定义。任何地方都可以访问声明为public的类成员。声明受保护的成员只能在类本身中、继承类和父类中访问。声明为private的成员只能由定义成员的类访问。

#11


6  

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.

保护:当您希望强制其他程序员(以及您自己)在访问和设置变量时使用类外的getter /setter时(但是您应该保持一致,并在类内使用getter和setter)。这个或private通常是设置所有类属性的默认方式。

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,将它设置为private也会使子类无法访问它。

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:此变量类型的值在所有范围内都可用,并在执行您的代码时调用。

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

Private:此类变量的值仅对其所属的类可用。私人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.

Private:只能在对象中引用,不能在子类中引用。

#16


0  

The Three Visibility Levels

三个水平能见度

In OOP PHP we have three visibility levels for properties and methods of a class: public, protected, and private. Visibility is declared using a visibility keyword to declare what level of visibility a property or method has. The three levels define whether a property or method can be accessed outside of the class, and in classes that extend the class.

在OOP PHP中,我们对类的属性和方法有三个可见性级别:public、protected和private。可见性是使用可见性关键字来声明属性或方法的可见性级别。这三个级别定义了是否可以在类之外和扩展类的类中访问属性或方法。

Public

公共

This level has no restrictions, which means it can be called in any scope. This means that a public property of an object can be both retrieved and modified from anywhere in a program — in the class, a subclass, or from outside of the class.

这个级别没有限制,这意味着可以在任何范围内调用它。这意味着对象的公共属性可以从程序中的任何地方检索和修改——在类中、在子类中,或者在类的外部。

Protected

受保护的

Protected properties and methods can be accessed from inside the class they are declared, or in any class that extends them. They can’t be accessed from outside the class or subclass.

保护的属性和方法可以从它们被声明的类内部或任何扩展它们的类中访问。它们不能从类或子类外部访问。

Private

私人

A private property or method can’t be accessed by a subclass of the class it is defined in. If you have a class with a protected property and a private property and then extend that class in the subclass, you can access the protected property, but not the private property.

私有属性或方法不能被它所定义的类的子类访问。如果您有一个具有受保护属性和私有属性的类,然后在子类中扩展该类,您可以访问受保护属性,但不能访问私有属性。

#1


1060  

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


997  

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

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:

例子:

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

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

  • 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:

例子:

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

例子:

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

注意:未定义属性:Daddy: $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

<?phpclass 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 classecho "#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 reflectionPrinting members the usual way.. (Without reflection)The name of grandpa is Mark Henry and he resides in the variable name1#Scenario 2: With reflectionPrinting members the 'reflect' way..The name of grandpa is Mark Henry and he resides in the variable name1The name of grandpa is John * and he resides in the variable name2The 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

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

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


78  

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()/brake()、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


68  

private - can be accessed from WITHIN the class only

private -只能从类内部访问

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.

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

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、protected和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.

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

  • 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


14  

/** * 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; // Worksecho $obj->protected; // Fatal Errorecho $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; // Worksecho $obj2->private; // Undefinedecho $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


8  

⚡️ 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手册中方法或变量的可见性。

#9


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.

更新:我现在使用的是protected的默认值,因为我发现它对于封装已经足够好了,并且在扩展类的时候不会受到影响(无论如何我都尽量避免这种情况)。只有当我有充分的理由使用另外两个时,我才会使用。

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.

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

#10


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、protected或private来定义。任何地方都可以访问声明为public的类成员。声明受保护的成员只能在类本身中、继承类和父类中访问。声明为private的成员只能由定义成员的类访问。

#11


6  

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.

保护:当您希望强制其他程序员(以及您自己)在访问和设置变量时使用类外的getter /setter时(但是您应该保持一致,并在类内使用getter和setter)。这个或private通常是设置所有类属性的默认方式。

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,将它设置为private也会使子类无法访问它。

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:此变量类型的值在所有范围内都可用,并在执行您的代码时调用。

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

Private:此类变量的值仅对其所属的类可用。私人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.

Private:只能在对象中引用,不能在子类中引用。

#16


0  

The Three Visibility Levels

三个水平能见度

In OOP PHP we have three visibility levels for properties and methods of a class: public, protected, and private. Visibility is declared using a visibility keyword to declare what level of visibility a property or method has. The three levels define whether a property or method can be accessed outside of the class, and in classes that extend the class.

在OOP PHP中,我们对类的属性和方法有三个可见性级别:public、protected和private。可见性是使用可见性关键字来声明属性或方法的可见性级别。这三个级别定义了是否可以在类之外和扩展类的类中访问属性或方法。

Public

公共

This level has no restrictions, which means it can be called in any scope. This means that a public property of an object can be both retrieved and modified from anywhere in a program — in the class, a subclass, or from outside of the class.

这个级别没有限制,这意味着可以在任何范围内调用它。这意味着对象的公共属性可以从程序中的任何地方检索和修改——在类中、在子类中,或者在类的外部。

Protected

受保护的

Protected properties and methods can be accessed from inside the class they are declared, or in any class that extends them. They can’t be accessed from outside the class or subclass.

保护的属性和方法可以从它们被声明的类内部或任何扩展它们的类中访问。它们不能从类或子类外部访问。

Private

私人

A private property or method can’t be accessed by a subclass of the class it is defined in. If you have a class with a protected property and a private property and then extend that class in the subclass, you can access the protected property, but not the private property.

私有属性或方法不能被它所定义的类的子类访问。如果您有一个具有受保护属性和私有属性的类,然后在子类中扩展该类,您可以访问受保护属性,但不能访问私有属性。