我何时以及为什么要在类中使用 public
, private
和 protected
函数和变量?它们之间有什么区别?
例子:
// Public
public $variable;
public function doSomething() {
// ...
}
// Private
private $variable;
private function doSomething() {
// ...
}
// Protected
protected $variable;
protected function doSomething() {
// ...
}
15 回答
公众:
将方法(函数)或属性(变量)声明为
public
时,可以通过以下方式访问这些方法和属性:声明它的同一个类 .
继承上述声明的类的类 .
此类之外的任何外来元素也可以访问这些内容 .
Example:
受保护:
什么时候您将方法(函数)或属性(变量)声明为
protected
,可以通过以下方式访问这些方法和属性:声明它的同一个类 .
继承上述声明的类的类 .
局外人无法访问这些变量 . "Outsiders",因为他们不是 object instances of the declared class itself.
Example:
确切的错误是这样的:
私人:
将方法(函数)或属性(变量)声明为
private
时,可以通过以下方式访问这些方法和属性:局外人无法访问这些变量 . 局外人认为他们不是 object instances of the declared class itself 甚至是 inherit the declared class. 的 class
Example:
确切的错误消息将是:
使用反射解剖爷爷班
这个主题并没有真正超出范围,我在这里添加它只是为了证明反射真的很强大 . 正如我在上面三个例子中所说的那样,
protected
和private
成员(属性和方法)不能在类之外访问 .但是,通过反射你甚至可以通过访问类之外的 protected 和 private 成员来做到超常!
嗯,什么是反思?
序言
我们有一个名为
Grandpas
的类,并说我们有三个属性 . 为了便于理解,请考虑有三个名字的爷爷:马克亨利
John Clash
Will Jones
让我们分别制作它们(分配修饰符)
public
,protected
和private
. 您非常清楚protected
和private
成员无法在课堂外访问 . 现在让我们反驳使用反射的陈述 .代码
Output:
常见的误解:
请不要混淆以下示例 . 正如您仍然可以看到的那样,如果不使用反射,则无法访问
private
和protected
成员Output:
调试功能
print_r
,var_export
和var_dump
是debugger functions . 它们以人类可读的形式呈现有关变量的信息 . 这三个函数将显示PHP 5对象的protected
和private
属性 . 不会显示静态类成员 .更多资源:
The PHP Manual - OOP Properties
The PHP Manual - OOP Visibility
Techflirt.com - Visibility in PHP Classes
Jordizle.com - Public, Private, Protected in PHP 5
PHP中的变量有三种不同的类型:
公共:此变量类型的值在所有范围内都可用,并在执行代码时调用 . 声明为:
public $examTimeTable;
Private:此类变量的值仅适用于它所属的类 .
private $classRoomComputers;
受保护:仅此类的值,仅在以继承形式或其子类授予Access时可用 . 通常使用
::
来授予父类的访问权限protected $familyWealth;
private - 只能从课堂上访问
protected - 可以从WITHIN类和INHERITING类访问
public - 也可以从代码OUTSIDE类访问
这适用于函数和变量 .
Visibility Scopes with Abstract Examples :: Makes easy Understanding
通过预先修复三个关键字(公共,受保护和私有)之一的声明来定义属性或方法的可见性
Public :如果属性或方法被定义为public,则意味着它可以被任何可以引用object的东西访问和操纵 .
Protected : 当属性或方法可见性设置为受保护成员时,只能在类本身以及继承和继承类中进行访问 . (继承: - 一个类可以拥有另一个类的所有属性和方法) .
Private : 当属性或方法可见性设置为private时,只有具有私有成员的类才能访问这些方法和属性(在类内部),尽管可能存在任何类关系 .
他们在那里允许不同级别的encapsulation
摘自:
http://php.net/manual/en/language.oop5.visibility.php
PHP手册对here这个问题有很好的解读 .
你用:
public
范围使该变量/函数可以从对象的任何位置,其他类和实例中获得 .当您希望变量/函数仅在其自己的类中可见时,
private
范围 .protected
范围如果要在扩展当前类(包括父类)的所有类中显示变量/函数 .More: (如需全面信息)
默认情况下,默认为所需的最低可见性通常被视为良好做法,因为这会促进数据封装和良好的界面设计 . 在考虑成员变量和方法可见性时,请考虑成员在与其他对象的交互中扮演的角色 .
如果您“编写接口而不是实现”,那么做出可见性决策通常非常简单 . 通常,变量应该是私有的或受保护的,除非您有充分的理由公开它们 . 使用公共访问者(getters / setters)来限制和规范对类内部的访问 .
使用汽车作为类比,速度,齿轮和方向等事件将是私有实例变量 . 您不希望驾驶员直接操纵空气/燃料比等事物 . 相反,您将有限数量的操作公开为公共方法 . 汽车的接口可能包括
accelerate()
,deccelerate()
/brake()
,setGear()
,turnLeft()
,turnRight()
等方法 .司机不知道也不应该关心汽车内部如何实施这些行动,并且暴露这些功能可能对驾驶员和其他人在路上造成危险 . 因此,设计公共接口并封装该接口背后的数据的良好做法 .
此方法还允许您更改和改进类中公共方法的实现,而不会破坏接口与客户端代码的约定 . 例如,您可以改进
accelerate()
方法以提高燃油效率,但该方法的使用将保持不变;客户端代码不需要更改,但仍然可以获得效率提升的好处 .Edit: 由于您似乎还在学习面向对象的概念(比任何语言的语法都难以掌握),我推荐使用Matt Zandstra的PHP对象,模式和实践的副本 . 这本书首先教我如何有效地使用OOP,而不仅仅是教我语法 . 我事先已经学会了语法,但是如果不理解OOP的"why"那就没用了 .
区别如下:
Public ::该类的任何用户都可以直接访问公共变量或方法 .
Protected ::类的用户无法访问受保护的变量或方法,但可以在继承自类的子类中访问 .
Private ::私有变量或方法只能在类内部访问它被定义 . 这意味着无法从扩展类的子进程调用私有变量或方法 .
PUBLIC :
public
范围:公共变量/函数可用于对象和其他类 .PROTECTED :
protected
范围:受保护的变量/函数可用于扩展当前类的所有类 .不!对象无法访问此范围
PRIVATE :
private
范围:私有变量/函数仅在定义它的当前类中可见 .不!扩展当前类的类无法访问此范围 .
不!对象无法访问此范围 .
阅读PHP手册中的方法或变量的Visibility .
考虑'何时':
我倾向于最初将所有内容声明为私有,如果我通常更容易将私有方法公开,而不是相反 . 那个_468021已被用在了 class 本身的任何地方 . 公共方法可能已经在任何地方使用,可能需要大量重写 .
Update :我现在的默认值为
protected
,因为我已经足够封装了,并且没有扩展类(我试图避免这种情况) . 只有我有充分的理由使用其他两个,我才会 .private
方法的一个很好的理由是实现该对象固有的东西,即使扩展类也不应该改变(事实上的原因,除了封装,如内部状态管理) . 最终,它仍然很容易追踪通常使用protected
方法的位置,所以我现在默认为protected
. 我承认,也许不是100%客观的经验 .恢复一个旧问题,但我认为一个非常好的方法来考虑这个就是你所定义的API .
public
- 标记为public的所有内容都是使用您的类/接口/其他人使用和依赖的API的一部分 .protected
- 不要被愚弄,这也是API的一部分!人们可以继承,扩展您的代码并使用任何标记为受保护的内容 .private
- 可以根据需要更改私有属性和方法 . 没有人可以使用这些 . 这些是您可以在不进行重大更改的情况下更改的唯一内容 .或者以Semver术语:
对任何事情
public
或protected
的更改应视为主要更改 .任何新的
public
或protected
应该(至少)MINOR只有新的/更改任何内容
private
可以是PATCH因此,在维护代码方面,最好小心你做了什么
public
或protected
因为这些是你向用户承诺的事情 .Public:当你声明一个变量或方法时是一个默认状态,任何东西都可以直接访问该对象 .
受保护:只能在对象和子类中访问 .
私有:只能在对象内引用,而不能在子类中引用 .
对我来说,这是理解三种属性类型最有用的方法:
Public :在您可以直接从代码中的任何位置访问和更改此变量时使用此选项 .
来自课外的示例用法:
Protected :当你想强迫其他程序员(和你自己)在访问和设置变量时使用类之外的getter / setter时使用它(但你应该保持一致,并且也要使用类中的getter和setter) . 这或
private
往往是您应该设置所有类属性的默认方式 .为什么?因为如果您在将来的某个时刻(甚至可能在5分钟内)决定您想要操作为该属性返回的值或在获取/设置之前对其执行某些操作,您可以在不重构任何地方的情况下执行此操作在你的项目中使用它 .
来自课外的示例用法:
Private :
private
属性与protected
属性非常相似 . 但区别的特征/区别在于,如果不使用父类的getter或setter,使private
也使得子类无法访问它 .所以基本上,如果你正在为一个属性使用getter和setter(或者如果它只在父类内部使用它并不意味着可以在其他任何地方访问)你也可以使它成为
private
,只是为了防止任何人试图直接使用它并引入错误 .子类内部的示例用法(扩展MyObject):