4

我正在使用 Enterprise Architect 制作 UML 类图并使用它生成 PHP5 代码。使用this,可以为属性创建 getter 和 setter,在代码中如下所示(仅显示相关行):

private $id;

public function getId()
{
    return $this->id;
}

/**
 * 
 * @param newVal
 */
public function setId($newVal)
{
    $this->id = $newVal;
}

我想使用魔术方法__get($property)__set($property, $value)而不是为每个属性使用单独的方法。有可能吗,如果有,怎么做?

对于吸气剂,它可能看起来像这样:

public function __get($property)
{
    switch ($property) {
        case 'id': return $this->id; break;
        default: return null;
    }
}
4

5 回答 5

6

不是真正的答案,但您应该考虑是否希望以这种方式完成。这不会带来任何好处,但会导致 IDE 代码完成功能出现问题,实际上会使代码维护变得更加困难。在我看来,魔术 __get/__set 应该只用于动态属性,否则使用单独的 set/get 方法或使用公共属性。这个答案几乎总结了它。

如果你仍然想走这条路,我会推荐更简单的方法

于 2013-03-28T20:29:27.343 回答
5

我同意此页面上的其他人的观点,即这是一种不好的做法,您应该坚持使用普通的老式 getter 和 setter 方法而不是魔术方法。一旦您需要在访问器/修改器中进行验证或其他计算,您的开关/案例就会爆炸。维护是一团糟,而且对继承并不友好。具有魔术方法的子类在技术上覆盖了父类的魔术方法。

但是,您可以通过使用 EA 的代码模板编辑器修改代码模板来做到这一点。

引用代码模板的 Enterprise Architect 用户指南

代码模板使您能够自定义现有语言的代码生成。例如:

  • 修改生成新文件时创建的文件头
  • 更改生成代码的样式(例如缩进或大括号位置)以匹配所需的编码标准
  • 处理特定的构造型以生成诸如专门的方法体和额外的方法之类的东西。

并进一步:

Enterprise Architect 的基本代码模板指定了从 UML 元素到给定编程语言的各个部分的转换。这些模板以纯文本形式编写,其语法与标记语言和脚本语言的某些方面相同。

这是代码编辑器的示例图片,其中加载了一些模板:

Enterprise Architect 代码模板编辑器

我不熟悉编辑器,也不熟悉他们使用的模板语言,所以我无法为您提供工作示例。但我想如果你真的想修改模板,你可以从那里弄清楚。

于 2013-03-30T18:44:37.153 回答
3

你可以像这样实现一个通用的魔法 getter/setter:

public function __get($name)
{
    if (property_exists($this, $name))
        return $this->{$name};
    return null;
}

public function __set($name, $value)
{
    if (property_exists($this, $name) && true/*Sanity checks here on $value instead of true if you want*/)
        $this->{$name} = $value;
}

但请记住这一点:

这对您的代码来说是一个非常糟糕的设计模式(即使它是符合 DRY 的做法)

此外,此代码严格等同于公开所有属性,并且不会因魔术方法而产生开销。好消息是,如果您想对每个 setter 执行相同的健全性检查,您可以在那里进行。

于 2013-03-30T18:18:03.843 回答
0

我想使用魔术方法 __get($property) 和 __set($property, $value) 而不是每个属性的单独方法。有可能吗,如果有,怎么做?

不应该定义每个属性。一个简单的数组容器对他们来说就足够了。所以,这正是您正在寻找的:

class Foo 
{
   private $container = array();

   public function __set($property, $value)
   {
      $this->container[$property] = $value;
   }

   public function __get($property)
   {
       if (array_key_exists($property, $this->container)){

          return $this->container[$property];

       } else {

          trigger_error(sprintf('Undefined property "%s"', $property));
       } 
   }

}

$foo = new Foo();
$foo->bar = "123";

print $foo->bar; // prints 123

$foo->id = "test string";

print $foo->id; // test string

print $foo->nonExistingProp; //issues E_NOTICE 

如果您坚持使用访问器/修饰符,那么您只需要重载它们。使用__call()

class Foo
{
    private $container = array();

    public function __call($method, array $args)
    {
        $property = substr($method, 3);

        if (substr($method, 0, 3) == 'get'){
           // getter is being used
           if (isset($this->container[$property])){
             return $this->container[$property];
           }
        }

        if (substr($method, 0, 3) == 'set'){
           //setter is being used
           $this->container[$property] = $args[0];
        }
    }
}

$foo = new Foo();

$foo->setId('__BAR__');
$foo->setStuff('__YEAH__'); 

print $foo->getId(); // prints __BAR__
print $foo->getStuff(); //prints __YEAH__
于 2013-04-03T19:26:37.793 回答
-1

不知道你是用IDE开发还是纯记事本。因为你问的是那种类型的问题,我猜它是记事本。然后,我建议您尝试众多免费 IDE 中的一个(我使用 NetBeans 已有一年,其他人可能也对 Eclipse 感到满意)。

如果您正在使用 EA 并做类模型,我猜您正在认真对待 OOP。如果是这样,您应该严格定义属性可见性,例如 Zend Framework 2 忘记public property可见性(也包括 a staticorpublic static属性)。然后你最终得到的属性是privateorprotected并且 getter/setter 的需求在地球上。

现在,如果您使用魔术__get()/__set()方法,您将如何调试您的代码?一个人怎么能知道在\One\Two\Three\Four有财产的班级里发生了什么\First\Second\Third::$bang?它是如何设置的?为什么我得到这个值而不是另一个?

另一方面 - 当使用遵循属性可见性的现代 IDE 时,请考虑这个类:

Class A
{
    private $foo;
    private $bar;

    protected $foobar;

    public function __get()
    {
        ...
    }

    public function __set()
    {
        ...
    }
}

没有 setter 或 getter。如果您正在编写您的代码,您的 IDE 不会提示您属性的名称(来自类外部),您必须将它们全部输入。使用 getter 和 setter(它们是让您可以访问私有或受保护属性的公共方法)您可以使用代码提示并加快您的开发过程,同时使用现代 OOP 原则。

于 2013-04-02T08:50:03.030 回答