将getter和setter用于不同的编程语言

时间:2011-01-13 18:47:11

标签: c++ python matlab setter getter

所以我知道有很多关于getter和setter的问题,但是我找不到与我的问题完全相同的东西。我想知道人们是否根据不同的语言改变了get / set的使用。我开始学习C ++,并被教导使用getter和setter。这就是我的理解:

在C ++(和Java?)中,变量可以是公共变量,也可以是私有变量,但我们不能混合使用。例如,我不能拥有一个只能在类中更改的只读变量。它要么全部公开(可以读取和更改它),要么全部是私有的(不能读取,只能在课堂内更改)。由于这个原因(可能还有其他原因),我们使用getter和setter。

在MATLAB中,我可以控制变量的“setaccess”和“getaccess”属性,这样我就可以将事物设为只读(可以直接访问属性,但不能覆盖它)。在这种情况下,我不觉得我需要一个getter,因为我可以做 class.property

此外,在Python中,它被认为是“Pythonic”,不使用getter / setter,只在需要时才将东西放入属性中。我真的不明白为什么在Python中拥有所有公共变量是可以的,因为这与我在使用C ++时所学到的相反。

我只是好奇其他人的想法是什么。你会为所有语言使用getter和setter吗?您是否只将它用于C ++ / Java并在MATLAB和Python中直接访问(这是我目前正在做的)?第二种选择被认为是不好的吗?就我的目的而言,我只是指简单的getter和setter(只返回/设置值,不做任何其他事情)。

谢谢!

10 个答案:

答案 0 :(得分:6)

实际上,getter和setter(以及隐藏它们的公共属性)对公共变量的改进很小,对quasi classes来说是一个非常好的指标。

答案 1 :(得分:3)

使用任何语言都可以使用所有公共变量。是的,我知道这与你学到的相反。

OO理论认为应该有一个稳定的公共API,私有变量,你可以做任何你想做的事情,以及一个你可以改变的实现,而不需要改变API。

这是正确的。 但不正确的是,私有API必须从其他类中无法访问。这只是OO理论中的一个错误。这是一个在纸面上听起来合理的想法,但在实践中几乎没有什么可去做,但会导致很多问题。

例如,多年前我需要在Delphi中子类化一个小部件,使其行为略有不同。你看到的不是很多,只是一点点。但我需要覆盖的代码称为私有方法,所以我无法覆盖它。相反,我需要覆盖这两种方法。当然,其他方法做了真正内部的事情,所以我最终基本上没有对小部件进行子类化,而是重复它,只是因为我做了一个小的改动。

OO理论声称它应该是这样的,因为恐怖恐怖,否则我的子类可能会停止使用下一版本的Delphi,如果超类改变了内部的东西!好吧,那又怎样?在那种情况下,我会解决它。

如果我使用部分内部数据,那就是我的问题。你不需要关心。你需要做的是以某种方式 flag “这个位是内部的,可能会改变,使用你自己的风险”。但是当你作为图书馆的开发者积极阻止我使用内部位时,你只会给我带来麻烦。

我现在几乎完全使用Python开发了十年,Python的开放从来没有给我带来任何问题,事实上已经多次保存了我的屁股(因为我可以通过简单地修补来修复框架错误在运行时修复代码)。在我使用它的两年中,Delphis标准的OO模型具有不同的保护级别,使我多次出现问题。

OO理论实际上是错误的。私人会员没有任何用处。一切都应该是公开的。根据我的经验,这适用于任何语言。

答案 2 :(得分:2)

我一般不会使用getter / setter,因为它们的存在表明我的班级活动不足以活着。

当我考虑需要它们时,无论语言是否支持混合访问wrt变量,我总是创建它们。只有我认为不这样做的时候是VB这样的语言支持“属性”,其中一个函数看起来就像一个变量访问。这里的关键原因是我不希望客户端绑定到属性由变量实现的事实。

答案 3 :(得分:2)

取决于你需要多么抽象。例如,我最近在抽象Text对象时需要在C ++中使用getter和setter。 Direct3D文本对象只持有一个字符串Text成员变量。但是,Direct2D Text对象必须重新创建和重新捕获,以及那种事情。如果我在设计原始抽象时选择了公共变量,我将不得不重新设计界面并更改所有相关代码。虽然我同意某些类别的getter和setter是没有意义的,但 某些情况下它们是必要的。

当然,具有属性的语言不需要这种东西。但从概念上讲,它们是相同的。在变量上定义属性只是一个带语法糖的getter和setter,虽然我支持语法糖,但它不会改变封装。我不会在语言基础上改变语言的封装设计。当然,社区关于封装是否是好事的意见是另一回事 - 这可能与您所看到的不同。在C ++中,封装的评级非常高,而Python社区对它的关注度较低。

答案 4 :(得分:0)

在Matlab中,每个额外的函数调用都会产生一些开销。因此,如果您不需要setter / getter,因为某些语言功能允许您完全相同,那么我真的不明白为什么您不想使用语言功能。

答案 5 :(得分:0)

作为一种动态脚本语言,Python不仅关注编译时约束,更关注灵活性。

Getters和setter(“property”只是getter + setter)允许更好的封装(检查有效性,只有getter,而不是setter;实现细节无关紧要 - 例如时间有小时,分钟,秒,但数据实际如何存储?谁关心?),以及未来的可扩展性(例如,setter代码可能会改变,消费者不关心)。

在像C ++这样的现代高效语言中,有内联,因此简单的getter / setter没有性能成本。

重点是,使用公共字段进行结构化和简单(小规模)编程,使用getter和setter进行大规模OOP项目。

答案 6 :(得分:0)

它实际上应该是完全一样的。在将某些东西公之于众之前,我总是提到现实生活中的情况。 每个人都可以访问我的汽车引擎吗?。大多数时候,答案是否定的,因为它是我的。人们可能会看到它,但他们无法改变它,因为他们想要。

因此,吸气者和制定者在每种语言中都很重要。唯一的问题是,在不同的语言中,如何设置访问权限是不同的。因此,正如您所述,如果Python确实想要将所有内容都设置为公开,那对我来说似乎是错误的。但是将MATLAB中的访问权限设置为某种扩展,对我来说似乎非常正确。

至于属性和吸气剂的差异。大多数情况下,如果两种语言都可用,那么就有一些规则。例如,在C#中,当属性的行为类似于普通变量并且确保该函数仅为O(1)时,鼓励使用属性。如果属性有更多的事情要做,比如额外的逻辑,那么应该创建一个函数[Rules of properties in C#]

总结:一切都应尽可能为private。自己创建接入点。属性是一个漂亮的布局中的getter和setter,因为它看起来像一个变量,并在需要时进行一些额外的检查。但不要太多。

答案 7 :(得分:0)

Python和C ++有不同的原则。 C ++和Java非常“静态”,并且有大量的编译时间检查,所以你应该在使用C ++和Java时利用它们:public与private,const-correctness等。另外它们没有属性,所以如果你发现你应该做一些参数验证,你不能轻易地将公共成员变量转换为getter-setter对而不改变语法和破坏现有代码。另一方面,Python是一种动态语言,允许每个人都做任何事情:你可以覆盖每个模块的每个变量,无法强制执行封装,没有静态类型检查等.Python人倾向于说“我们是”所有成年人,“并且你不应该依赖未记录的行为并使用单元测试而不是编译时检查。我不能判断什么是更好的,但一般来说你应该坚持你的语言的既定惯例。

答案 8 :(得分:0)

你是对的 - 现代Matlab OOP中不需要“简单”的getter和setter;您提到的访问修饰符是“正确的方法”。

在新的MCOS Matlab类中,无论是否定义自定义getter / setter,访问类属性的语法都是相同的。客户端总是可以访问属性foo作为“obj.foo”。如果您决定添加特殊的“get.foo”和“set.foo”方法,当客户端使用“obj.foo”语法访问该属性时,Matlab会隐式调用它们。因此,它不像Java或C ++中的公共字段那样真正“直接访问”。这就像Scala的“统一访问”模型。 (我觉得 ”。”您提到的语法和声明性访问控制保持简单,并允许您在需要时透明地添加自定义逻辑,而无需提前编写样板代码。 Java中用户定义的getter和setter的普遍存在部分是因为该语言缺乏这些功能。

在旧式Matlab类中,反之亦然:所有字段都是私有的,因此您必须编写自己的getter / setter。我见过的约定是编写一个与获取或设置的属性同名的方法,具体取决于你将其称为“foo(obj)”还是“foo(obj,NewValue)”。

答案 9 :(得分:0)

考虑一下c ++的这个片段:

class C {
public:
    const T &get_t() const { return t; }
    void set_t(const T &value) { t = value; }

private:
    T t;
};

在此示例中,由于存取器功能,成员“t”实际上是C的公共接口的一部分。但是,通常情况下,访问器功能更复杂,执行计算,管理并发等。在这些情况下,访问“t”被封装在访问器函数中的所需操作。

在C ++中,使用直接数据成员访问来封装访问操作与其他操作是不可能的,因此我们使用访问器函数。事实上,我们使用访问器功能,即使只是简单的访问是必要的,因为

  1. 如果您将直接访问与访问者功能混合使用,则很难记住哪些成员使用哪种访问权限,

  2. 很难预测您是否可能需要访问者在将来执行更多操作。如果您这样做,并且您使用了访问者,则可以在不更改公共接口(API)的情况下更改访问者。

  3. 通过属性,Python使用自然的直接访问语法提供访问的一致性,以及向数据成员访问添加功能的能力,但是(隐藏的)getter和setter。

    此外,数据隐私是通过python中的约定使用成员名称上的前导下划线来实现的,以向用户发出特定成员不属于类的公共接口的信号。用户违反惯例,但如果它破坏,他们可以自由地保留这两个部分。 Python程序员称之为“我们都是成年人”编程。

    class C:
        def get_t(self):
            return self._t
    
        def set_t(self, t):
            self._t = t
    
        t = property(get_t, set_t)
    

    在这个例子中,_t通常是私有的,并通过其属性接口访问,但仍然可以与其他数据成员共享一种自然的直接访问语法。