PHP面向对象开发访问限定修饰符、内部对象的概念与应用举例

发布于 2022-11-22  505 次阅读


内容纲要

一、访问修饰限定符的概念

访问修饰限定符用于限定属性或方法可以被访问的位置,前面的public就是访问修饰限定符的一种。

public:公有,在类内和类外都可以访问。

protected:受保护,只可以在相关类内访问。

private:私有,只可以在当前类内访问。

私有存在的意义就是提供给类内方法访问,方法内的代码也属于类内,只可以在当前类的访问的属性或方法,一般都用在方法内。

属性必须有访问限定修饰符,方法可以不加,默认是public。

使用修饰限定符的步骤:

二、类内部对象

1.概念

$this是类内部对象,它是PHP提供的在类内部调用类属性和类方法的一个对象,他可以用在类方法内使用,并且只能在类结构内使用。

私有方法protected和private都是必须通过类内部对象访问,因为它们被限定无法在类外通过对象访问。

所有的公有方法不仅可以在类外通过对象访问,也可以在类内通过$this访问。

$this对象可以访问任意修饰符修饰的方法和属性(仅针对当前类)

因为类的内部访问属性和方法也需要对象,所以就有了$this对象。

将$this打印测试一下:

class MyTest{
    private $name="Proking";
    public function dump(){
        var_dump($this);
    }
}

$obj=new MyTest();
$obj->dump();
//object(MyTest)#1 (1) { ["name":"MyTest":private]=> string(7) "Proking" }

针对不同的类,$this的值是不同的。

class MyTest{
    private $name="Proking";
    public function dump(){
        var_dump($this);
    }
}

$obj=new MyTest();
$obj->dump();

class Abc{
    public $age=18;
    private $birthday=0420;
    function dump(){
        var_dump($this);
    }
}
$A=new Abc();
$A->dump();

/*
针对MyTest类:
object(MyTest)#1 (1) { ["name":"MyTest":private]=> string(7) "Proking" 
针对Abc类:
object(Abc)#2 (2) { ["age"]=> int(18) ["birthday":"Abc":private]=> int(272) }
*/

如何在类结构内访问类方法?

class Abc{
    public $age=18;
    private $birthday=0420;
    function dump(){
        global $A;
        echo $A->age;
    }
}
$A=new Abc();
$A->dump();

上面代码的原理是在类中调用已经实例化的对象,然后通过这个对象来访问类方法。

虽然 对象是在类外实例化的,但是最后访问还是在类内,所以即使是私有的属性也可以访问。

注意dump方法内有个global $A; 他代表接下来使用的$A 是全局变量而不是局部变量,如果不使用global关键字,$A是未定义的。

但是,这样做有个很大的弊端就是,在类结构外实例化的对象的名称被限制死了,如果我实例化的对象是$B,仍然会产生$A未定义的错误,而且某些情况我们可能会实例化不止一个对象,所以通过这个方法访问类内部的属性显然很鸡肋。

而$this 内部对象就能够很好地解决这个问题。

2.使用$this对象

$this对象可以在类的内部调用类的成员,如果我们需要在类中调用某个方法或者属性,就可以通过$this来实现:

class OrderBuy{
    public $name="依维柯大金杯";
    protected $price=8.88;
    private $account=100;
    public function order(){
        //下单并扣除余额,返回剩余的余额
        $this->account-=$this->price;
        $str="你购买了:".$this->name.",支付:".$this->price."你的钱包还剩:".$this->account;
        return $str;
    }
    public function dump(){
        //调用下载操作,获取返回内容,打印输出。
        $rs=$this->order();
        echo $rs;
    }
}

$CP=new OrderBuy();
$CP->dump();
//你购买了:依维柯大金杯,支付:8.88你的钱包还剩:91.12

这是一个简单的示例,很多情况下我们都需要在类内调用类内的成员,本例子中,最后只调用了dump方法就实现了下单,因为在类内的dump方法内就已经调用了order方法,如果不使用$this,还需要在类外调用一次order方法,并且order方法无法得知商品相关信息。不使用$this,这种简单的需求固然也是可以实现的,但是非常麻烦,并且要在类外产生大量代码,这就违背了面向对象编程的初衷:提高代码运行效率,节省代码量, 一次编写,处处调用,提高代码重复利用率。

3.原理

  • class是定义类结构,属于非执行段代码,因此会被加载到代码段(编译阶段)
  • new是实例化对象,先判定类在内存(代码段)是否存在
  • 类不存在,报错;
  • 类存在,将类内部的属性部分复制一份,然后在内存(堆区)开辟一块内存空间,将属性放到里面,同时内部有一个指针指向类的内存空间(代码段)
  • 对象访问属性即访问的是对象空间里存储的部分
  • 对象访问方法是对象通过内部指针找到类空间中的方法,然后在内存(栈区)开辟运行
  • $this是系统在方法内置的对象通用名字
  • 对象在调用方法的时候,系统会自动找到对象所保存的内存地址(堆区),然后把地址赋值给$this
  • 方法内部的$this就代表调用当前$this所在方法的外部对象
  • $this的本质是函数内部的一个局部变量,只是系统自动对其进行赋值,而且一定是调用方法的对象本身
  • 面向对象编程代码运行内存关系:

届ける言葉を今は育ててる
最后更新于 2022-11-22