像 C# 中那样处理 PHP 属性(getter & setter)

Handling PHP properties like those in C# (getter & setter)

我一直在做一些研究,想知道在 PHP class 中使用属性是否可以像 C# 一样完成,我发现这些问题有一些很好的答案和指示,但并没有真正帮助我:

虽然,正如我所说,这些给出了很好的答案,但我仍然不能对这些下定决心,例如,我希望能够做一些事情,例如:

class Foo 
{
    public $bar
    {
        get { return $this->bar; }
        set { $this->bar = value; }
    }
}

可是我做不到!

在 PHP 的约束下,最好的方法是什么?

我能想到的是这样的:

class user
{
    private static $link;
    private static $init;

    private function __construct ()
    {
        global $link;
        static::$link = $link;
    }

    public static function __INIT__ ()
    {
        return static::$init = (null === static::$init ? new self() : static::$init);
    }

    public static $username;

    public function username( $value = '' )
    {
        if ( $value == '' || empty ( $value ) || !$value )
            return static::$username;
        else
            static::$username = $value;
    }
}

这就是 PHP 魔术方法的用途。它们允许您通过中介方法动态设置属性。在这里,让我给你举个例子:

abstract class GetterSetterExample
{
    public function __get($name)
    {
        $method = sprintf('get%s', ucfirst($name));

        if (!method_exists($this, $method)) {
            throw new Exception();
        }

        return $this->$method();
    }

    public function __set($name, $v)
    {
        $method = sprintf('set%s', ucfirst($name));

        if (!method_exists($this, $method)) {
            throw new Exception();
        }

        $this->$method($v);
    }
}

class Cat extends GetterSetterExample
{
    protected $furColor;

    protected function getFurColor()
    {
        return $this->furColor;
    }

    protected function setFurColor($v)
    {
        $this->furColor = $v;
    }
}

$cat = new Cat();
$cat->furColor = 'black';

是啊...我也很害怕。

这就是为什么大多数人都满足于使用 Cat 中的方法,但是 public。显然有关于添加 "real" getter 和 setter 的讨论,但是那些出于可读性、语义和原则方面的考虑而讨厌它们的人之间似乎存在很多冲突...

也许你需要考虑是否真的有必要。只是一个shorthand写getter和setters.

private String _name;

public String Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

与以下功能完全相同:

private $_name;

public function getName()
{
    return $_name;
}

public function setName($name)
{
    $_name = $name;
}

只有调用上的区别:

C#  : Object.Name = "This is my Name";
PHP : Object->setName ("This is my Name");

如果您真的更喜欢 C# 语法(在我看来这只是一种习惯),我认为 Flosculus 的答案是唯一的选择。如果您了解代码的作用,它并没有那么复杂。 供参考:

__set() is run when writing data to inaccessible properties.
__get() is utilized for reading data from inaccessible properties.

在此示例中,furColor 是不可访问的,因为它是一个受保护的变量。

那么这里发生了什么 $cat->furColor = 'black

  • furColor 无法访问,因此魔法方法 __set 正在调用。
  • 它在 GetterSetterExample 中创建一个名为 setFurColor 的 setter 并检查它是否存在。
  • 是的,它确实存在,因为 Cat 实现了它。
  • 调用
  • setFurColor 并设置变量。

在最后,此代码的作用与上面示例中的一般 getter 和 setters 完全相同。它只是一个 'workaround' 来模拟 C# 的属性。 那么回到我对这个答案的第一个问题,有必要吗?在我看来不是。 PHP 不支持属性,因此您尝试模拟它的原因没有明确的含义。 一般 getter 和 setters 是可行的方法,如我的示例所示,它做的事情完全相同。 魔术方法很慢,如果你想以类型安全的方式做到这一点,祝你好运。 Flosculus 的示例代码并不复杂,但这种方法可能会变得(不必要的)复杂。