且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《PHP精粹:编写高效PHP代码》——1.5节public、private以及 protected

更新时间:2022-02-24 06:16:32

本节书摘来自华章社区《PHP精粹:编写高效PHP代码》一书中的第1章,第1.5节public、private以及 protected,作者:(美)  Davey Shafik,更多章节内容可以访问云栖社区“华章社区”公众号查看

1.5 public、private以及 protected
在本章列举的示例中,在所有的方法和属性前面都使用了一个public关键字。这表明这些方法和属性在这个类以外的地方都可以读写。pubic是一个访问修饰符(access modifier),还有另外两个替代修饰符:private和protected。让我们依次来了解这些修饰符吧。

1.5.1 public
如果你看到代码省略了访问修饰符,这就是一个默认设置。在编码时加上public修饰符是一个良好的习惯,但即便不加,默认设置也同样发生。因为无法保证这种默认设置将来是否会发生改变,所以使用这个关键字表明开发者有意选择公开这个方法或属性。

1.5.2 private
创建private方法或属性意味着这个方法或属性只会在其声明的类中可见。如果你尝试从外部访问它,那么你会看到一个错误。下面是一个很好的示例,我们为本章前面定义的Courier类增加一个获取特定国家航运率的方法。这只需要在类的内部增加一个计算运费的函数,因此我们将它声明为私有的:


《PHP精粹:编写高效PHP代码》——1.5节public、private以及 protected

使用私有方法表明我们设计的函数只能在该类的内部使用,禁止在应用程序的其他地方调用。明确选择哪些函数是否公开是面向对象应用程序的一个重要组成部分。

1.5.3 protected
一个受保护的属性或方法类似于私有的方法,这是因为这个属性或方法不是到处可见的。在声明的类中任意地方都可以访问这个属性或方法,更重要的是,这个属性或方法也可以在任何继承这个类的类中访问。在Courier类的示例中有一个私有的方法getShippingRateForCountry()(由calculateShipping()方法调用),在Courier类中这个方法工作正常,事实上,在Courier的子类中它也同样正常工作。然而,如果子类需要以自己的方式重新实现calculateShipping()方法时,将无法使用getShippingRateForCountry()方法。
使用protected意味着在该类的外部不能调用这些方法,但是它的子类却被看做“内部”,使我们有机会使用这些方法或者读取这些属性。

1.5.4 选择正确的可见性
为每一个属性或方法选择正确的可见性,图1.2描述了这个决策过程:


《PHP精粹:编写高效PHP代码》——1.5节public、private以及 protected

一个普遍的原则是,如果没有必要从类的外部访问,这些属性或方法就不应该公开。对于类而言,有一个较小的可见区域可以让代码的其他部分使用起来更简单,开发新手也更容易理解这段代码。如果将这些属性或方法设为私有,那么今后需要扩展这个功能时就会受到限制,因此只有万不得已才能这么做,否则,该属性或方法应该受保护。

1.5.5 使用getter和setter来控制可见性
上一节概述了决定一个属性或方法需要哪种访问修饰符的过程。另一种管理可见性的方法是将所有的属性都标记为protected,并且只允许使用getter和setter方法来访问它们。顾名思义,这两种方法可以用于获取和设置属性值。
getter和setter方法就像下面这样:


《PHP精粹:编写高效PHP代码》——1.5节public、private以及 protected

这似乎有些矫枉过正,在某些情形下那可能是一个好的评价。另外,对于追溯访问属性的对象代码而言,这是非常有用的方法。每次访问属性时,getter和setter方法都会显现出来,根据需要提供了一个钩或拦截点。可以连接这些方法到日志以查看更新了哪些信息,或者添加一些访问控制逻辑,或者很多理由中的任何一个。无论选择使用setter和getter方法,或者直接访问属性,正确的做法是根据不同的应用程序而改变。这两种方法使我们可以决定哪种方式是最合适的工具。
下划线和可见性
在PHP 4中,任何东西都是公开的,对非公开的方法和属性使用下划线作为前缀是一个惯例。在过时的应用程序和当前的一些编码规范中仍可见到,虽然下划线不是必要的,有些人不喜欢使用,但重点是它符合项目的编码规范(更多内容见第8章)。

1.5.6 使用神奇的_get和_set方法
虽然本节的主题是getter和setter,但还要兜一个小小的圈子来查看PHP中可用的两种神奇方法:_get()和_set()。
当访问一个不存在的属性时会调用这两个方法,如果这听起来不合常理,看了下面的代码示例你会更明白:


《PHP精粹:编写高效PHP代码》——1.5节public、private以及 protected

当试图读取或者写入类中不存在的一个属性时,将会调用上面的代码。$data属性确实包含数值,但从类的外部来看,我们只是在正常地访问属性。例如,我们可能这样写代码:


《PHP精粹:编写高效PHP代码》——1.5节public、private以及 protected

从这个角度来说,我们无法看出$name属性不存在,但对象表现出它仿佛存在。神奇的__get()和__set()方法允许我们改变幕后发生的事情。在这里可以添加任何需要的逻辑,让不同名称的属性有不同的表现、检查值或者你能想到的任何东西。所有PHP神奇的方法都为我们提供了放入代码的地方来响应某个特定的事件;既然这样,访问一个不存在的属性也成为可能。