为什么继续使用具有不可变对象的getter? [英] Why continue to use getters with immutable objects?

查看:120
本文介绍了为什么继续使用具有不可变对象的getter?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用不可变对象变得越来越常见,即使当手头的程序从来不意味着并行运行。但是我们仍然使用getter,每个字段需要3行样板,每次访问需要5个额外字符(在你最喜欢的主流OO语言中)。虽然这可能看起来很微不足道,许多编辑者仍然从程序员那里消除了大部分的负担,但它似乎仍然是不必要的努力。



继续使用的原因是什么访问器对不可变对象的直接字段访问?具体来说,强制用户使用访问器(对于客户端或库编写器)是否有优势,如果是这样,它们是什么?






请注意,我指的是不可变的 对象,与此不同问题,一般指对象。要清楚,对不可变对象没有设置器。

解决方案

我说这实际上是语言相关的。如果你原谅我,我会谈一谈C#,因为我认为这将有助于回答这个问题。



我不知道你是否熟悉C#,但它的设计,工具等非常直观和程序员友好。

C#的一个特性(它也存在于Python,D等等),它帮助这是属性;一个属性基本上是一对方法(一个getter和/或setter),在外部看起来就像一个实例字段:你可以分配给它,你可以从它读取就像一个实例变量。



但是C#数据类型有时也有GetXYZ()和SetXYZ()方法,有时他们甚至直接暴露他们的领域......这就提出了一个问题:你如何选择要做什么?



Microsoft有一个伟大的指南的C#属性和何时使用getters / setters代替


属性应该表现为它们是字段;如果方法不能,则不应该将其更改为属性。在以下情况下,方法优于属性:




  • 该方法执行耗时的操作。该方法看起来比设置或获取字段值所需的时间更慢。

  • 该方法执行转换。访问字段不会返回其存储的数据的转换版本。

  • 获取方法具有可观察到的副作用。检索字段的值不会产生任何副作用。

  • 执行顺序很重要。设置字段的值不依赖于其他操作的发生。

  • 连续调用该方法两次会创建不同的结果。

  • 方法是静态的,但返回一个可以被调用者改变的对象。检索字段的值不允许调用者更改该字段存储的数据。

  • 该方法返回一个数组。


注意,这些指南的整个目标是使所有属性看起来像字段



因此,使用属性而不是字段的唯一真正原因是:


  1. 您要封装,yada yada。

  2. 您需要验证输入。

  3. 您需要从数据到)其他地方。

  4. 您需要转发二进制(ABI)兼容性。我是什么意思?如果你有时,在路上,决定你需要添加某种验证(例如),然后将字段更改为属性,并重新编译库将取决于它的任何其他二进制文件。但是,在源代码级别,没有什么会改变(除非你采用地址/引用,你可能不应该这样)。

现在让我们回到Java / C ++和不可变数据类型。



哪些点适用于我们的场景?


  1. 有时它不适用,因为不可变的数据结构的整个要点是存储数据,而不是具有(多态)行为(比如String数据类型)。

    如果你要隐藏它并且不做任何操作,存储数据的意义是什么?

    但是有时它会应用(例如说你有一个不可变的树) - 你可能不想公开元数据。

    但是在这种情况下,你显然会隐藏你不想公开的数据,你不会一直在第一次提出这个问题地点! :)

  2. 不适用;

  3. 不适用,否则不能使用字段!

  4. <

    现在,Java和C ++没有属性,但方法占据了它们的位置上面的建议仍然适用,并且没有属性的语言的规则变为:



    如果(1)不需要ABI兼容性, (2)你的getter的行为就像一个字段(即它满足上面的MSDN文档的要求),那么你应该使用一个字段而不是一个getter。



    重要的一点是,没有一个是哲学的;所有这些指南都基于程序员期望的 。显然,一天结束时的目标是(1)完成工作,(2)保持代码可读/可维护。上面的指南已经发现有助于实现这一点 - 你的目标应该是做任何适合你的想法,将使这种情况。


    Using immutable objects has become more and more common, even when the program at hand is never meant to be ran in parallel. And yet we still use getters, which require 3 lines of boilerplate for every field and 5 extra characters on every access (in your favorite mainstream OO language). While this may seem trivial, and many editors remove most of the burden from the programmer anyways, it is still seemingly unnecessary effort.

    What are the reasons for the continued use of accessors versus direct field access of immutable objects? Specifically, are there advantages to forcing the user to use accessors (for the client or library writer), and if so what are they?


    Note that I am referring to immutable objects, unlike this question, which refers to objects in general. To be clear, there are no setters on immutable objects.

    解决方案

    I'd say this is actually language-dependent. If you'll excuse me I'll talk about C# a bit, since I think it'll help answer this question.

    I'm not sure if you're familiar with C#, but its design, tools, etc. are very intuitive and programmer-friendly.
    One feature of C# (which also exists in Python, D, etc.) that helps this is the property; a property is basically a pair of methods (a getter and/or a setter) which, on the outside, look just like an instance field: you can assign to it and you can read from it just like an instance variable.
    Internally, of course, it's a method, and it can do anything.

    But C# data types also sometimes have GetXYZ() and SetXYZ() methods, and sometimes they even expose their fields directly... and that begs the question: how do you choose which to do when?

    Microsoft has a great guideline for C# properties and when to use getters/setters instead:

    Properties should behave as if they are fields; if the method cannot, it should not be changed to a property. Methods are better than properties in the following situations:

    • The method performs a time-consuming operation. The method is perceivably slower than the time that is required to set or get the value of a field.
    • The method performs a conversion. Accessing a field does not return a converted version of the data that it stores.
    • The Get method has an observable side effect. Retrieving the value of a field does not produce any side effects.
    • The order of execution is important. Setting the value of a field does not rely on the occurrence of other operations.
    • Calling the method two times in succession creates different results.
    • The method is static but returns an object that can be changed by the caller. Retrieving the value of a field does not allow the caller to change the data that is stored by the field.
    • The method returns an array.

    Notice that the entire goal of these guidelines is to make all properties look like fields externally.

    So the only real reasons to use properties instead of fields would be:

    1. You want encapsulation, yada yada.
    2. You need to verify the input.
    3. You need to retrieve the data from (or send the data to) somewhere else.
    4. You need forwards binary (ABI) compatibility. What do I mean? If you sometime, down the road, decide you need to add some sort of verification (for example), then changing a field to a property and recompiling your library will break any other binaries that depends on it. But, at the source-code level, nothing will change (unless you're taking addresses/references, which you probably shouldn't be anyway).

    Now let's get back to Java/C++, and immutable data types.

    Which of those points apply to our scenario?

    1. Sometimes it doesn't apply, because the whole point of an immutable data structure is to store data, not to have (polymorphic) behavior (say, the String data type).
      What's the point of storing data if you're going to hide it and do nothing with it?
      But sometimes it does apply (e.g. say you have an immutable tree) -- you might not want to expose metadata.
      But then in that case, you would obviously hide the data you don't want to expose, and you wouldn't have been asking this question in the first place! :)
    2. Doesn't apply; there's no input to verify because nothing is changing.
    3. Doesn't apply, otherwise you can't use fields!
    4. May or may not apply.

    Now Java and C++ don't have properties, but methods take their place -- and so the advice above still applies, and the rule for languages without properties becomes:

    If (1) you don't need ABI compatibility, and (2) your getter would behave just like a field (i.e. it satisfies the requirements in the MSDN documentation above), then you should use a field instead of a getter.

    The important point to realize is that none of this is philosophical; all these guides are all based on what the programmer expects. Obviously, the goal at the end of the day is to (1) get the job done, and (2) keep the code readable/maintainable. The guide above has been found to be helpful in making this happen -- and your goal should be to do whatever suits your fancy that will make that happen.

    这篇关于为什么继续使用具有不可变对象的getter?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆