我正在使用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)
代替每个属性的单独方法。是否可能,如果可能,怎么样?
对于getter来说,它看起来像这样:
public function __get($property)
{
switch ($property) {
case 'id': return $this->id; break;
default: return null;
}
}
答案 0 :(得分:6)
不是真的答案,但你应该考虑是否要这样做。这不会带来任何好处,但会导致IDE代码完成功能出现问题,实际上会使代码维护更加困难。在我看来,magic __get / __ set应仅用于动态属性,否则使用单独的set / get方法或使用公共属性。 This answer几乎总结了它。
如果你还想走这条路,我会推荐simpler approach。
答案 1 :(得分:5)
我同意本页面上的其他人认为这是不好的做法,你应该坚持使用普通的吸尘器和魔术方法。一旦您需要在访问器/更改器中进行验证或其他计算,您的开关/案例就会爆炸。这是一个混乱的维护,而不是完全友好的继承。使用魔术方法的子类在技术上会覆盖父级的魔法。
但是,您可以通过使用EA的代码模板编辑器修改代码模板来实现这一点。
引自Enterprise Architect User Guide on Code Templates:
代码模板使您可以自定义现有语言的代码生成。例如:
- 修改生成新文件时创建的文件标题
- 更改生成代码的样式(例如缩进或支撑位置)以匹配所需的编码标准
- 处理特定的构造型以生成专门的方法体和额外的方法。
并进一步:
Enterprise Architect的基本代码模板指定从UML元素到给定编程语言的各个部分的转换。模板以纯文本形式编写,其语法与标记语言和脚本语言的某些方面共享。
以下是代码编辑器的示例图片,其中加载了一些模板:
我不熟悉编辑器或他们使用的模板语言,所以我无法为您提供一个工作示例。但是如果你真的想修改模板,我想你可以从那里弄明白。
答案 2 :(得分: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;
}
但要牢记这一点:
此外,此代码完全等同于将所有属性公开,并且由于魔术方法,您不会有开销。 好消息是如果你想对每个setter执行相同的健全性检查,你可以在那里进行。
答案 3 :(得分: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__
答案 4 :(得分:-1)
我不知道您是使用IDE进行开发还是使用纯记事本。因为你问这类问题我猜它是记事本。然后我建议您尝试使用许多免费IDE中的一个(我使用NetBeans多年,其他人也可能对Eclipse感到满意)。
如果您正在使用EA并且正在使用类模型,我猜您正在认真对待OOP。如果是这样,您应该严格定义属性可见性,例如, Zend Framework 2忘记了public property
可见性(结果还包括static
或public static
属性)。然后你得到的属性为private
或protected
,并且地球上需要吸气剂/定位器。
现在,如果您使用魔术__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()
{
...
}
}
没有制定者或吸气者。如果您正在编写代码,您的IDE将不会提示您属性的名称(来自课外),您必须长时间键入它们。使用getter和setter(是公共方法,允许您访问私有或受保护的属性)您可以使用代码提示并在使用现代OOP原则的同时进行开发过程。