PHP面向对象编程 - 使用getter和setter来预防属性值的改变?

3
我已经了解了封装性,并且我的理解是,它的好处是防止改变属性的值?(如果我误解了,请警告我)。
然而,它有一个setter方法可以改变属性private $bar的值。 我是否误解了?因为它不再防止改变属性的值。
<?php 

    class Foo 
    {
        private $bar = 3;

        public function getbar()
        {
            return $this->bar;
        }
        public function setBar($bar)
        {
            $this->bar = $bar;
        }
    }

    $foo = new Foo();


    echo $foo->getbar(); //Print '3'

    $foo->setBar("Hello");  

    echo $foo->getbar();  //Print 'Hello'

    ?>

所以现在我很困惑为什么他们不正常使用公共属性。
class Foo2 
{
    public $bar = 3;
}
$foo2 = new Foo2();

echo $foo2->bar;  // Print '3'
$foo2->bar = 'Hello';
echo $foo2->bar; //Print 'Hello';

尝试调用 $foo->bar 然后看看会得到什么 :) - TurtleTread
1
封装的优点通常不是为了防止某些事情发生,而是允许控制对属性的操作以及如何进行操作。这也隐藏了内部属性的确切实现。例如,内部属性可以是标量变量或具有自己逻辑的内部属性对象。 - arkascha
1
在当前情况下,这两者是等价的。但是,如果您扩展 Foo,情况将会改变,因为 bar 将不会被继承。 - Sebastian
不需要。只需运行$foo->bar并查看结果即可。打开您的错误报告。您需要亲眼看到这个。 - TurtleTread
@TurtleTread - 这并不是重点。他在问为什么在当前上下文中不直接使用public而是使用带有getter和setter的private - Sebastian
2个回答

1
我认为您应该尽可能避免使用公共字段、getter和setter。封装并不是“防止更改属性值”,而是要隐藏类的具体实现方式。类的所有方法都必须定义一种行为,但不是如何确切地实现该类。
让我举个例子。 传统的方式是:
Dog dog = new Dog();
dog.setBall(new Ball());

但在现实世界中,你不能把球扔给狗。你只能告诉狗去拿球,然后狗会决定是否想要去拿球。
面向对象编程的方式有点像这样:
Dog dog = new Dog();
dog.take(new Ball());
Ball ball = dog.give();  

上面的代码演示了封装如何工作。我建议阅读一篇为什么getter和setter是有害的文章。它详细解释了这个问题。


0
啊,我记得当我第一次阅读这些内容时也曾对此感到困惑。其实这个想法是为了强制限制对属性修改的访问。如果你有一些函数直接设置对象值的属性,那么它会覆盖你已经设定的属性。通过指定特定的函数并将访问权限限制在类本身或子类(受保护的可见性)中,你的风险就会降低。此外,你可以对你正在设置的数据运行验证检查和其他处理。而且如果其他开发人员也在项目上工作,并直接设置属性呢?如果你看右边,似乎网站已经有几篇文章回答了这个问题:为什么要使用getter和setter?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接