动态检索类属性值

时间:2013-10-29 21:57:18

标签: php

我来自.Net背景,我试图将我的大脑包裹在我习惯的编程模式中,但是在PHP中。

我有一个带关联数组属性的类。我想将一些(但不是全部)关联数组键“提升”到类级属性。在C#中,我通常会这样做:

//C# Code
class MyClass{
    private Dictionary<string, string> attributes = new Dictionary<string,string>();

    //Get/Set the ID from the private store
    public string ID{
        get { return (attributes.ContainsKey("ID") ? attributes["ID"] : "n/a"); }
        set { attributes.Add("ID", value); }
    }
}

这允许我的对象控制缺失属性的默认值。在PHP中,我找不到任何直接执行此操作的方法。我的第一个解决方法是使用函数:

//PHP Code
class MyClass{
  private $attributes = array();

  //Get the ID    
  public function getID(){
    return (array_key_exists('ID', $this->attributes) ? $this->attributes['ID'] : 'n/a');
  }
  //Set the ID
  public function setID($value){
    $this->attributes['ID'] = $value;
  }
}

虽然调用语法略有不同,但我的每个属性都有两个方法。此外,使用这些对象的代码当前正在检查对象变量,因此无法找到函数。

然后我开始沿着对象本身的__set__get的神奇方法路径走下去,而switch case上的$name传入并设置/获取我的{{1}}局部变量。不幸的是,如果直接修改底层数组,则不会调用这些方法。

所以我的问题是,在PHP中是否有可能有一个类级别的属性/变量,直到它被使用才能计算出来?

2 个答案:

答案 0 :(得分:2)

PHP没有属性,因为C#程序员会理解这个概念,所以你必须使用方法作为getter和setter,但原理完全相同。

class MyClass {
    private $attributes = array ();

    public function getSomeAttribute () {
        if (!array_key_exists ('SomeAttribute', $this -> attributes)) {
            // Do whatever you need to calculate the value of SomeAttribute here
            $this -> attributes ['SomeAttribute'] = 42;
        }
        return $this -> attributes ['SomeAttribute'];
    }
    // or if you just want a predictable result returned when the value isn't set yet
    public function getSomeAttribute () {
        return array_key_exists ('SomeAttribute', $this -> attributes)?
            $this -> attributes ['SomeAttribute']:
            'n/a';
    }

    public function setSomeAttribute ($value) {
        $this -> attributes ['SomeAttribute'] = $value;
    }
}

基本上你的实现基本的想法,但它确实意味着很多“样板”代码。理论上你可以用__get和__set来避免很多这样的事情,但是我强烈反对那些因为它们会导致大量的混乱和令人讨厌的逻辑纠结,比如“如果在类中设置值而不是从外面?”你遇到的问题。

答案 1 :(得分:0)

在PHP中您可以这样做:

<?php
class MyClassWithoutParams{
    function test(){
      return $this->greeting . " " . $this->subject;
    }
}

$class = new MyClassWithoutParams();
$class->greeting = "Hello";
$class->subject = "world";

echo $class->greeting . " " . $class->subject . "<br />"; //Hello World
echo $class->test(). "<br />"; //Hello World
?>

您无需定义任何属性,getter或setter即可使用属性。当然最好这样做,因为它使代码更容易阅读,并允许eclipse(或任何IDE)的自动完成功能来理解你在寻找什么 - 但如果你只是寻找最懒的方式来实现实体,也可以。

更常见的方法是使用关联数组而不是类 - 但是在数组上你不能定义方法。

<?php
$array = new array();

$array["greeting"] = "Hello";
$array["subject"] = "World";

echo $array["greeting"] . " " . $array["subject"]; //Output: Hello World
?>