不使用setter和getter真的那么错吗?

14 浏览
0 Comments

不使用setter和getter真的那么错吗?

我在PHP方面还比较新手。在其他编程语言(比如JAVA)中,对于每个变量我都习惯使用setter和getter,但是在PHP编程中,可能因为其灵活性,觉得使用setter和getter有点浪费时间。通常,我更倾向于将类属性设置为public并直接操作它们,这样更简单。但问题是这样做,我感觉好像在违背面向对象的原则。\n不使用setter和getter真的那么错误吗?为什么是或者为什么不是?你们大多数时候是怎么做的?

0
0 Comments

使用getter和setter方法是否真的那么错误?

在PHP中,如果只考虑PHP而不是C#、Java等(在这些语言中编译器会进行优化),我发现getter和setter是一种浪费资源的做法,因为你只需要代理私有字段的值,而不需要做其他任何操作。

在我的设置中,我创建了两个简单的类,一个类有五个私有字段,通过五个getter/setter对字段进行封装(这看起来几乎和Java代码一模一样),另一个类有五个公共字段,然后在创建实例后调用memory_get_usage()。使用getter/setter的脚本使用了59708字节的内存,而使用公共字段的脚本使用了49244字节的内存。

在任何重要的类库(例如网站框架)的上下文中,这些无用的getter和setter方法会导致内存占用量巨大。我在PHP中为我的雇主开发了一个框架(这是他们的选择,而不是我的。如果我有选择的话,我不会选择PHP用于此目的,但是话虽如此,PHP并没有对我们施加任何不可逾越的限制),当我将类库重构为使用公共字段而不是getter和setter时,每个请求的内存使用量至少减少了25%。

__get()、__set()和__call()这些“魔术”方法在处理接口更改时非常有用。当您需要将字段迁移到getter/setter(或getter/setter迁移到字段)时,它们可以使依赖代码对此过程透明。对于解释性语言来说,即使使用Eclipse PDT或Netbeans提供的相对较好的代码敏感性支持,查找字段或方法的所有使用也有点困难,因此这些魔术方法对于确保旧接口仍然委托给新功能非常有用。

假设我们有一个使用字段而不是getter/setter开发的对象,并且我们想将名为'field'的字段重命名为'fieldWithBetterName',因为'field'不合适,或者不再准确描述其用途,或者完全错误。并且我们想要将名为'field2'的字段更改为从数据库中延迟加载其值,因为初始值是未知的,使用一个getter...

class Test extends Object {
    public $field;
    public $field2;
}

变成

class Test extends Object {
    public $fieldWithBetterName = "LA DI DA";
    private $_field2;
    public function getField2() {
        if ($this->_field2 == null) {
            $this->_field2 = CrapDbLayer::getSomething($this->fieldWithBetterName);
        }
        return $this->_field2;
    }
    public function __get($name) {
        if ($name == 'field') {
            Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
            return $this->fieldWithBetterName;
        }
        elseif ($name == 'field2') {
            Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
            return $this->getField2();
        }
        else return parent::__get($name);
    }
}
$t = new Test;
echo $t->field;
echo $t->field2;

(顺便提一下,那个“extends Object”的部分只是我几乎所有东西都使用的一个基类,它具有一个__get()和__set()的声明,当访问未声明的字段时会抛出异常)

您也可以使用__call()方法进行反向操作。这个例子相当脆弱,但很容易清理:

class Test extends Object {
    public $field2;
    public function __call($name, $args) {
        if (strpos($name, 'get') === 0) {
            $field = lcfirst($name); // 欺骗,我知道。php 5.3或更高版本。不过没有它也不难做到。
            return $this->$field;
        }
        parent::__call($name, $args);
    }
}

在PHP中,如果setter必须执行某些操作,或者getter必须延迟加载某些内容,或者确保某些内容已经创建,那么使用getter和setter方法是很好的选择;但是,如果getter和setter除了代理字段之外什么都不做,特别是使用上述几种技术来管理接口更改,它们是不必要且浪费资源的。

0
0 Comments

在编程中,使用getter和setter的目的是为了在一个地方添加逻辑来修改字段,而不是在每个想要修改或检索字段的地方都进行修改。此外,使用getter和setter还可以在类级别上控制字段的行为。

然而,有人认为不使用getter和setter也可以达到相同的效果,因为它们认为这种方法会增加代码的复杂性,并且不值得这样做。他们认为直接访问字段可以提高代码的可读性和性能。

这种争论的出现是因为不同的编程风格和个人偏好。有些人喜欢使用getter和setter来封装字段,以便在以后修改字段时可以更容易地添加逻辑。而另一些人则认为直接访问字段更简洁和高效。

对于那些支持使用getter和setter的人来说,他们认为这种方法可以提高代码的可维护性和灵活性。通过使用getter和setter,可以将字段的修改逻辑集中在一处,以便在需要修改时可以更方便地进行更改。此外,使用getter和setter还可以在类级别上对字段进行控制,以确保字段的有效性和一致性。

然而,对于那些不支持使用getter和setter的人来说,他们认为这种方法会增加代码的复杂性,并且不值得这样做。他们认为直接访问字段可以提高代码的可读性和性能。此外,他们认为使用getter和setter会产生不必要的开销,因为它们会引入额外的方法调用和内存开销。

为了解决这个问题,可以根据个人偏好和项目需求来决定是否使用getter和setter。如果项目要求需要对字段进行封装和控制,那么使用getter和setter可能是一个好的选择。然而,如果项目要求更注重性能和简洁性,那么直接访问字段可能更合适。

总之,是否使用getter和setter是一个个人偏好和项目需求的问题。使用getter和setter可以提高代码的可维护性和灵活性,但也会增加代码的复杂性和开销。因此,选择是否使用getter和setter应该根据具体情况进行权衡。

0
0 Comments

是否使用setter和getter真的那么错?

不使用属性访问器的主要问题是,如果发现以后需要将字段更改为属性-例如,在子类中将其作为计算属性使用-那么会破坏API的客户端。对于发布的库来说,这是不可接受的;对于内部库来说,这只是需要大量的工作来修复问题。

对于私有代码或小型应用程序,可能可以随意使用。IDE(或文本编辑器)可以让您生成访问器样板并使用代码折叠隐藏它。可以说,这使得使用getter和setter在机械上相当容易。

请注意,一些编程语言具有合成默认字段+getter+setter的功能-例如,Ruby通过元编程实现,C#具有自动实现的属性。而Python则完全避开了这个问题,它允许您重写属性访问,将属性封装在需要它的子类中,而无需事先烦扰它。(这是我最喜欢的方法。)

如果需要将属性转化为计算属性而不破坏向后兼容性,则可以使用__get和__set。

“synthetise”是什么意思?是指“synthesize”还是“simulate”?

是指合成。在Ruby中,调用attr_accessor :foo之后,类实际上会包含方法def foo; ; end和相应的setter-它们不是通过“伪造”的方式实现的,例如使用method_missing和哈希表。对于C#来说也是一样,编译器会生成一个真正的私有字段和简单的访问器方法。

我从来没见过这个词-我猜它是英国的词。我知道这个词的拼写是“synthesize”。没问题!只是好奇你指的是哪个词。

哦,你是指拼写。那只是我英语非母语的表现。(我使用-ise,因为这样我就不需要记住-ize不正确的例外情况。)维基百科说,避免使用-ise是美式英语,英式英语允许在任何地方都使用这两种拼写,首选是根据你遵循的风格指南而定。

加上字母t的差异。

那是一个常见的错误。

0