博客列表 >PHP第二十九天作业-构造函数\__set和__get魔术方法实例-2018-05-10

PHP第二十九天作业-构造函数\__set和__get魔术方法实例-2018-05-10

HeartofSunny的博客
HeartofSunny的博客原创
2018年05月10日 23:59:41944浏览

魔术方法类文件Student.class

<?php

class Student
{
    private $name = '';
    private $cls = '';
    private $age = 0;
    private $data=[];

    //构造方法
    public function __construct($name='',$cls='',$age=0){
        $this->name = $name;
        $this->cls = $cls;
        $this->age = $age;
    }

    //查询器
    public function __get($name)
    {
        $msg = null;
        if(isset($this->$name)){
            $msg = $this->$name;
        }elseif (isset($this->data[$name])) {
            $msg = $this->data[$name];
        } else{
            $msg = '无此属性';
        }
        return $msg;
    }

    //设置器
    public function __set($name,$value)
    {
        if (isset($this->$name)) {
            $this->$name = $value; //输出属性
        }else {
            //如果属性不存在,则创建它并保存到类属性$data数组中
            $this->data[$name] = $value;
        }
    }
}

运行实例 »

点击 "运行实例" 按钮查看在线实例

index.php

<?php

require 'class/Student.php';

//实例化Student类
$student = new Student('张三丰','三年级',12);

//输出学生信息
echo '姓名:',$student->name,'<br>';
echo '班级:',$student->cls,'<br>';
echo '年龄:',$student->age,'<br>';
//echo '爱好:', $student->hobby, '<br>';

echo '<hr>';

$student->name ='张无忌';
$student->cls = '一年级';
$student->age = 10;
echo '姓名:',$student->name,'<br>';
echo '班级:',$student->cls,'<br>';
echo '年龄:',$student->age,'<br>';
//给一个不存在的属性赋值,类中并无hobby字段
$student->hobby = '购物';
echo '爱好:', $student->hobby, '<br>';

//使用类属性设置器__set()再创建一个新属性
$student->sex = '男';
echo '性别:', $student->sex, '<br>';

//直接查看用户自定义的类属性$data数组的内容,此时会输出二个自定义数据
echo '用户自定义属性<pre>'.print_r($student->data,true).'</pre>';

运行实例 »

点击 "运行实例" 按钮查看在线实例

总结:

        在类当中,设计通用的set和get方法,可以简化对属性的读写,这种方法不同于针对于独立的属性的普通的get和set方法,后者针对每个属性,都必须提供一对方法,前者针对所有属性,因此,可以看作是批量定义set和get方法的策略。

        另外一种常见的魔术方法是construct,在这里作为对照进行介绍。

        第一,关于访问权限修饰符。construct设计为public,那么可以在new创建对象时,系统会调用构造方法对对象进行初始化,否则将无法实例化此类(常用于纯静态类,或者单例模式当中),而set和get,设计为private并不影响功能本身,即系统调用这些方法是不受访问权限所左右的。而设计为public,则可以直接调用这些方法本身。

        第二,关于返回值。get方法的返回值,作为属性结果,而construct和set方法的返回值是没有任何意义的,并不会被采用。如下:

        echo $obj->pro = "value";

        打印的值将是value,而不论set方法的返回值是什么。

        第三,关于使用的情境。需要取得$obj->pro值的情况下,会首先寻找公共的pro属性,如果没有找到,会查看是否有get方法,并将其返回值作为结果,如果没有get方法,将会寻找私有属性,找到后会报错,如果私有属性也找不到,会临时创建一个公共属性。

        在$obj->pro = "value"的情况下,会首先寻找公共pro属性,如果没有找到,会启用set方法,如get类似。

        上述语法,在类本身也有用,如果类的某个方法有$obj->pro的表达式,那么,它会首先寻找属性,然后采用get方法,当然,私有属性和公共属性都会被首先寻找,然后才会考虑get方法,set方法类似。

        但是isset魔术方法,是优先于get方法的,也就是说,如果客户端代码如下:

        isset($obj->pro),会首先检查是否有pro公共变量,然后检查isset方法,如果有,将会读取isset方法,然后将返回值确定为检查结果,如果没有,才会考虑用get方法的过程。

        第四,关于继承。这些魔术方法均会被子类继承,继承时,父类可以访问子类中的非私有变量和方法,但是无法访问私有变量和方法。这个问题会导致一个值得注意的细节,比如在父类当中,我们把set方法定义为赋值给一个叫_pro的变量,那么,如果子类直接继承这个set方法,它将能够有效赋值给父类当中定义的私有变量,但是对于子类当中的私有变量,它并没有多态的权限,因此,无法赋值。

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议