属性(Property)一个小文章

  老A   2019-12-11 13:55:16  0  572  
关注 喜欢 鲜花 收藏 评论

属性用于表征类的状态,从访问的形式上看,属性与成员变量没有区别。 你能一眼看出 $object->foo 中的 foo 是成员变量还是属性么?显然不行。 但是,成员变量是就类的结构构成而言的概念,而属性是就类的功能逻辑而言的概念,两者紧密联系又 相互区别。比如,我们说People类有一个成员变量 int $age ,表示年龄。那么这里年龄就是属性 , $age 就是成员变量。

再举个更学术化点的例子,与非门:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class NotAndGate extends Object{
    private $_key1;
    private $_key2;

    public function setKey1($value){
        $this->_key1 = $value;
    }

    public function setKey2($value){
        $this->_key2 = $value;
    }

    public function getOutput(){
        if (!$this->_key1 || !$this->_key2)
            return true;
        else if ($this->_key1 && $this->_key2)
            return false;
    }
}

与非门有两个输入,当两个输入都为真时,与非门的输出为假,否则,输出为真。上面的代码中,与非 门类有两个成员变量, $_key1 和 $_key2 。但是有3个属性,表示2个输入的 key1 和 key2 ,以及表示输出的 output 。

成员变量和属性的区别与联系在于:

  • 成员变量是一个“内”概念,反映的是类的结构构成。属性是一个“外”概念,反映的是类的逻辑意义。
  • 成员变量没有读写权限控制,而属性可以指定为只读或只写,或可读可写。
  • 成员变量不对读出作任何后处理,不对写入作任何预处理,而属性则可以。
  • public成员变量可以视为一个可读可写、没有任何预处理或后处理的属性。 而private成员变量由于外部不可见,与属性“外”的特性不相符,所以不能视为属性。
  • 虽然大多数情况下,属性会由某个或某些成员变量来表示,但属性与成员变量没有必然的对应关系, 比如与非门的 output 属性,就没有一个所谓的 $output 成员变量与之对应。

在Yii中,由 yii\base\Object 提供了对属性的支持,因此,如果要使你的类支持属性, 必须继承自 yii\base\Object 。Yii中属性是通过PHP的魔法函数 __get() __set() 来产生作用的。 下面的代码是 yii\base\Object 类对于 __get() 和 __set() 的定义:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public function __get($name)              // 这里$name是属性名
{
    $getter = 'get' . $name;              // getter函数的函数名
    if (method_exists($this, $getter)) {
        return $this->$getter();          // 调用了getter函数
    } elseif (method_exists($this, 'set' . $name)) {
        throw new InvalidCallException('Getting write-only property: '
            . get_class($this) . '::' . $name);
    } else {
        throw new UnknownPropertyException('Getting unknown property: '
            . get_class($this) . '::' . $name);
    }
}

// $name是属性名,$value是拟写入的属性值
public function __set($name, $value)
{
    $setter = 'set' . $name;             // setter函数的函数名
    if (method_exists($this, $setter)) {
        $this->$setter($value);          // 调用setter函数
    } elseif (method_exists($this, 'get' . $name)) {
        throw new InvalidCallException('Setting read-only property: ' .
            get_class($this) . '::' . $name);
    } else {
        throw new UnknownPropertyException('Setting unknown property: '
            . get_class($this) . '::' . $name);
    }
}
文章不允许评论