深入PHP(第三版)——对象基础之public、private、protected管理类的访问

探讨PHP中类属性的public、private与protected可见性,如何通过访问控制预防代码bug,以及通过具体示例ShopProduct类展示如何实现打折功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

博客来自《深入PHP 面向对象、模式与实践》第三版
类中的元素可以被声明为public、private或protected。

在任何地方都可以访问public属性和方法。
只能在当前类中才能访问private方法或属性,即使在子类中也不能访问
//注:在继承中,子类默认继承了父类所有的public和protected方法(但是没有继承private方法或属性)
可以在当前类或子类中访问protected方法或属性,其他外部代码无权访问

这对我们有什么用吗?可见性关键字允许我们只公开类中客户需要的部分,这给对象设置了一个清晰的接口。
通过阻止客户访问特定的属性,访问控制也有助于预防代码中的bug。例如,我们想要在ShopProduct对象支持打折功能,可以增加$discount属性和setDiscount方法。

//ShopDiscount类
public $dicount=0;

//···
function setDiscount($num)
{
$this->discount=$num;
}

除了通过setDiscount设置折扣量,还可以创建getPrice()方法来获取已经实施的折扣。

//ShopProduct类
function getPrice()
{
  return ($this->price------$this->discount)
}

这里有个问题。我们只想公开调整过的价格,但是客户也可以很容易的绕过getPrice()方法来访问$price属性:

print $product1->price;

源码
ShopProduct类

class ShopProduct{
    public $title;
    public $producerMainName;
    public $producerFirstName;
    public $price;
    //设置属性
    public $discount=0;

    function __construct($title,$producerMainName,$producerFirstName,$price)
    {
        $this->title=$title;
        $this->producerMainName=$producerMainName;
        $this->producerFirstName=$producerFirstName;
        $this->price=$price;
    }

    public function getSummaryLine()
    {
        $base=$this->title."($this->producerMainName)";
        $base.=$this->producerFirstName;
        return $base;
    }
    public function getProducer()
    {
        return "{$this->producerFirstName}"."{$this->producerMainName}";
    }
    //添加了打折的方法
    public function setDiscount($num)
    {
        $this->discount=$num;
    }
    //添加获取实施折扣的方法
    public function getPrice()
    {
        return $this->price---$this->discount;
    }
}

BookProduct书类

class BookProduct extends ShopProduct {
    public $numPages;
    public function __construct($title, $producerMainName, $producerFirstName, $price,$numPages)
    {
        parent::__construct($title, $producerMainName, $producerFirstName, $price);
        $this->numPages=$numPages;
    }

    public function getNumberOfPages()
    {
        return $this->numPages;
    }
    public function getSummaryLine()
    {
        $base=$this->title."($this->producerMainName)";
        $base.=$this->producerFirstName;
        $base.=":page count-{$this->numPages}";
        return $base;
    }
}

实例化类

include "3.5.1.php";

$product2=new BookProduct("Exile on Coldharbour Lane","The","Alabama 3",12,60.33);

print $product2->price;//能绕过getPrice方法来访问price是因为price是public属性,可供外面任何地方调用。

这里将输出原始的价格,而不是希望展示折扣价。我们可以通过将$price属性设置为private来禁止直接输出。

在这里插入图片描述
这样做可以阻止直接访问,强制客户使用getPrice()方法。任何试图从ShopProduct类外访问$price属性的操作都将失败。对于类外面的世界来说,这个属性就像不存在一样。
在这里插入图片描述
设置属性为private有时是一种过于严格的方案,因为private属性不能被子类访问。假设我们的商业规则是只有书不能打折,这时可以覆写getPrice()方法,让它返回$price属性,并且不进行折扣计算

//BookProduct类
   public function getPrice()
    {
      return $this->price;
    }

由于在ShopProduct类中而不是BookProduct类中声明属性$price为private,所以这里无法访问这个属性。解决办法是声明$price为protected,让子类也可以访问。
在这里插入图片描述

要记住的是,protected属性或方法不可能在声明它的类层次之外被访问。protected属性和方法只能在被定义的类中或者该类的子类中被访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kinghiee

助力蛋白粉计划

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值