Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 考虑到对象封装,getter是否应该返回不可变属性?_Java_Oop - Fatal编程技术网

Java 考虑到对象封装,getter是否应该返回不可变属性?

Java 考虑到对象封装,getter是否应该返回不可变属性?,java,oop,Java,Oop,当getter返回一个属性时,比如返回一个其他相关对象的列表,该列表及其对象是否应该是不可变的,以防止类外的代码在主父对象不知道的情况下更改这些对象的状态 例如,如果一个Contact对象有一个getDetailsgetter,它返回一个ContactDetails对象的列表,那么调用该getter的任何代码: 可以从该列表中删除ContactDetail对象,而Contact对象不知道它 可以在联系人对象不知道的情况下更改每个联系人详细信息对象 那么我们应该在这里做什么呢?我们应该信任调用代码

当getter返回一个属性时,比如返回一个其他相关对象的
列表
,该列表及其对象是否应该是不可变的,以防止类外的代码在主父对象不知道的情况下更改这些对象的状态

例如,如果一个
Contact
对象有一个
getDetails
getter,它返回一个
ContactDetails
对象的
列表,那么调用该getter的任何代码:

  • 可以从该列表中删除
    ContactDetail
    对象,而
    Contact
    对象不知道它
  • 可以在
    联系人
    对象不知道的情况下更改每个
    联系人详细信息
    对象

  • 那么我们应该在这里做什么呢?我们应该信任调用代码并轻松返回可变对象,还是千方百计为每个可变类创建一个不可变类?

    如果您可以控制调用代码,那么最重要的是您所做的选择在所有正确的位置都有很好的文档记录。

    我过去常常返回只读版本的列表,或者至少是一份。但是列表中包含的每个对象都必须是可编辑的,除非它们在设计上是不可变的。

    实际上取决于上下文。但通常情况下,应该尽可能编写防御性代码(返回数组副本,返回集合周围的只读包装等)。在任何情况下,都应该清楚地记录它

    这是一个您是否应该在代码中“防御”的问题。如果你是你的类的(唯一)用户,并且你信任自己,那么绝对不需要不变性。然而,如果不管发生什么情况,这段代码都需要工作,或者您不信任您的用户,那么就让所有外部化的东西都不可变


    也就是说,我创建的大多数属性都是可变的。偶尔的用户会把这搞砸,但这又是他/她的错,因为有明确的记录表明,变异不应该通过通过getter接收的可变对象发生。

    我想你会发现,每个gettable都是不可变的是非常罕见的

    您可以做的是在此类对象中的属性发生更改时触发事件。这也不是一个完美的解决方案


    文档可能是最实用的解决方案;)

    这取决于上下文。如果列表是可变的,那么当列表本身有一个非常好的API时,将主类的API与方法混为一谈是没有意义的

    然而,如果主类不能处理突变,那么您需要返回一个不可变列表,并且列表中的条目本身也可能需要是不可变的


    不过,不要忘记,您可以返回一个自定义列表实现,它知道如何安全地响应变异请求,无论是通过触发事件还是直接执行任何必需的操作。事实上,这是一个使用内部类的好时机的经典示例。

    当我刚开始时,我仍然深受隐藏数据OO原则LOL的影响。我会坐下来思考,如果有人更改某个属性公开的对象的状态,会发生什么。我是否应该使它们仅为外部呼叫者阅读?我应该不暴露他们吗

    收藏品将这些焦虑带到了极致。我的意思是,有人可以在我不看的时候把收藏中的所有物品都拿走

    我最终意识到,如果你的对象对它们的外部可见属性和类型有着如此紧密的依赖关系,那么如果有人在一个不好的地方触碰它们,你的体系结构就是有缺陷的


    有充分的理由使您的外部属性为只读且其类型不可变。但这是一个极端的情况,不是典型的情况,伊姆霍。

    你的第一要务应该是遵守德米特定律或“告诉-不要问”;告诉对象实例要做什么,例如

    contact.print( printer ) ;  // or
    contact.show( new Dialog() ) ; // or
    contactList.findByName( searchName ).print( printer ) ;
    
    面向对象的代码告诉对象做事情。程序代码获取信息,然后根据该信息进行操作。要求一个对象揭示其内部细节破坏了封装,这是过程代码,而不是健全的OO编程,正如Will已经说过的,这是一个有缺陷的设计


    如果遵循德米特定律,则对象状态的任何变化都会通过其定义的界面发生,因此副作用是已知的,并且是可控的。您的问题消失了。

    在Java中的集合、列表、集合或映射的特定情况下,使用
    return Collections.unmodifiableList(List)很容易将不可变视图返回给类


    当然,如果支持数据仍有可能被修改,那么您需要制作列表的完整副本。

    首先,setter和getter表示OO不正确。通常,OO的概念是你要求对象为你做一些事情。设置和获取是相反的。Sun应该想出一些其他的方法来实现JavaBeans,这样人们就不会接受这种模式并认为它是“正确的”

    其次,您拥有的每个对象本身都应该是一个世界——一般来说,如果要使用setter和getter,它们应该返回相当安全的独立对象。这些对象可能是不变的,也可能不是不变的,因为它们只是一级对象。另一种可能性是,它们返回的本机类型总是不可变的。所以说“setter和getter应该返回不可变的东西”没有太多意义

    至于创建不可变对象本身,实际上应该始终将对象中的成员设置为final,除非有充分的理由不这样做(final应该是默认值,“mutable”应该是覆盖该默认值的关键字)。这意味着只要可能,对象都是不可变的

    至于预定义的准对象对象,我建议您将其包装为col