PHP魔术方法之__set()和__get()

先来看一段代码:

class Article{
    //私有成员属性
    private $title = '标题';

    //受保护的成员属性
    protected $author = '作者';

    //公有成员属性
    public $introduce = '简介';
}

$article = new Article();
var_dump($article -> title);
var_dump($article -> author);
var_dump($article -> introduce);

对象直接访问类中的private和protected成员属性时,会报一个Fatal error的错误,提示“Cannot access private property”或者“Cannot access protected property”。

1、魔术方法__get()

如果对象要直接访问类中的private和protected成员属性呢? PHP给我们提供了一个魔术方法“__get()”,用于获取private和protected成员属性。

class Article{

    //私有成员属性
    private $title = '标题';

    //受保护的成员属性
    protected $author = '作者';

    //公有成员属性
    public $introduce = '简介';

    //获取private和protected成员属性
    public function __get($name){·
        if(isset($this -> $name)) {
            return $this->$name;
        }
        return false;
    }

}

$article = new Article();
var_dump($article -> title);
var_dump($article -> author);
var_dump($article -> introduce);

执行结果如下:

string(6) "标题" string(6) "作者" string(6) "简介"

可以看出,__get()魔术方法并不需要我们显示的去调用;类本身会隐式的去调用此方法。而且,private和protected成员属性都可以通过此魔术方法获取相应的数据。

2、魔术方法__set()

如果对象要直接对类中的private和protected成员属性赋值呢? PHP给我们提供了一个魔术方法“__set()”,用于对private和protected成员属性进行赋值操作。

class Article{

    //私有成员属性
    private $title = '标题';

    //受保护的成员属性
    protected $author = '作者';

    //公有成员属性
    public $introduce = '简介';

    //获取private和protected成员属性
    public function __get($name){
        if(isset($this -> $name)) {
            return $this->$name;
        }
        return false;
    }

    //设置private和protected成员属性
    public function __set($name, $value){
        if(isset($this -> $name)){
            $this -> $name = $value;
        }
    }
}

$article = new Article();
$article -> title = '文章标题';
$article -> author = '文章作者';
$article -> introduce = '文章简介';

var_dump($article -> title);
var_dump($article -> author);
var_dump($article -> introduce);

执行结果如下:

string(12) "文章标题" string(12) "文章作者" string(12) "文章简介"

__set()魔术方法也不需要显示的调用;类本身也会隐式的去调用此方法。而且,private和protected成员属性都可以通过此魔术方法去设置相应的值。特别注意一点,所有的魔术方法都必须声明为public,各位可以去实现一遍代码,测试便知。

其实get()和set()这两个魔术方法都是PHP“重载(overload)”特性的体现。PHP中的"重载"与其它绝大多数面向对象语言不同。传统的"重载"是用于提供多个同名的类方法,但各方法的参数类型和个数不同。而PHP中的“重载”是指动态地“创建”类属性和方法,即通过魔术方法(magic methods)来实现。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极客猴

Python 中连接字符串效率最高的方式是哪种呢?

在编码过程中,我们经常需要对字符串进行连接处理操作。如果我们能使用优雅的方式来处理字符串连接,那么程序内存开销会小很多。

862
来自专栏精讲JAVA

Gof设计模式之工厂模式(四)

定义 工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 工厂模式...

1878
来自专栏北京马哥教育

Python 的正则表达式彩蛋

虽然我觉得在 Python 的标准库里的确有不少很恶心的库,但是 re 库肯定不属于这种。尽管它真的有年头没有更新了,但是在我看来,仍不失为动态语言中最好的库...

2787
来自专栏lgp20151222

Java的常量接口思考,项目中的常量是放在接口里还是放在类里呢?

最近在看一本书 Java与模式,里面提了一句不建议使用常量接口,甚至举了个java源码的反例,

1151
来自专栏算法channel

其他|c++几个容易混淆的点

希望时间的流逝不仅仅丰富我们的阅历,更重要的是通过提炼让我们得以升华,走向卓越。 1编译出错 一段时间没写c/c++的程序了,最近公司一个项目底层的核心算法是...

3265
来自专栏老马说编程

计算机程序的思维逻辑 (1)

程序大概是怎么回事 计算机就是个机器,这个机器主要由CPU、内存、硬盘和输入输出设备组成。计算机上跑着操作系统,如Windows或Linux,操作系统上运行着各...

19510
来自专栏Crossin的编程教室

【Python 第26课】 操作list

上周给list开了个头,知道了什么是list。假设我们现在有一个list: l = [365, 'everyday', 0.618, True] 除了用for...

35611
来自专栏生信宝典

为啥我的Python这么慢 - 项查找 (二)

上一篇为啥我的Python这么慢, 字符串的加和和join被陈群主分享到biopython-生信QQ群时,乐平指出字典的写法存在问题,并给了一篇知乎的链接htt...

1809
来自专栏desperate633

设计模式之策略模式(Strategy Pattern)引子设计原则1提取鸭子的的行为设计原则2实现鸭子的行为整合实现我们设计的鸭子类策略模式总结

策略模式,是我们接触到的第一个设计模式,也是较容易理解的一个模式。 我们可以给它下一个定义: ** 定义了算法族,分别封装起来,让它们之间可以互相转换,此模...

803
来自专栏小詹同学

Python系列之零——从零说起!!!

2017年可谓是人工智能元年,要问哪个行业最火,詹小白不敢确定,但要问哪个编程语言最热门,好吧,詹小白还是不敢说太满。但是!至少从舆论Pytho...

35610

扫码关注云+社区