duanke1984 2013-10-29 21:57
浏览 18
已采纳

动态检索类属性值

I'm coming from a .Net background and I'm trying to wrap my brain around a programming pattern that I'm used to but in PHP.

I've got a class with an associative array property. I'd like to "elevate" some, but not all, of the associative array keys to class-level properties. In C# I'd normally do something like this:

//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); }
    }
}

This allows my object to control default values for missing properties. In PHP I couldn't find any way to do this directly. My first workaround was to just use functions:

//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;
  }
}

This works although the calling syntax is slightly different and I've got two methods per property. Also, the code that is consuming these objects is currently inspecting object variables so functions wouldn't be found.

Then I started going down the magic method paths of __set and __get on the object itself and just switch case on the $name that's passed in and setting/getting my local variables. Unfortunately these methods don't get invoked if you modify the underlying array directly.

So my question is, is it possible in PHP to have a class-level property/variable that doesn't get calculated until it gets used?

  • 写回答

2条回答 默认 最新

  • douxing8939 2013-10-29 22:29
    关注

    PHP doesn't have properties as C# programmers would understand the concept, so you'll have to use methods as the getter and setter, but the principle is exactly the same.

    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;
        }
    }
    

    You essentially got the basic ideas right with your implementation, but it does mean a lot of "boilerplate" code. In theory you can avoid a lot of that with __get and __set, but I'd strongly advise against those as they can lead to epic amounts of confusion and nasty logical tangles like the "what happens if the value is set within the class instead of from outside?" issue that you've run into.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏