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 设置字段与创建新对象_Java_Oop - Fatal编程技术网

Java 设置字段与创建新对象

Java 设置字段与创建新对象,java,oop,Java,Oop,我之前在阅读时看到以下引语: “许多所谓的面向对象语言都有setter,当对象上有setter时,就可以将其转换回数据结构。” 文章继续暗示,这不是最佳实践,从长远来看可能会损害您开发的应用程序 我是一名CompSci学生,有C、Java、PHP、Ruby等方面的经验。。。因此,我对OOP作为一个概念和实践相当熟悉,但我绝不是一个专家 我想我的问题归结起来是: 在编写OO程序时,访问字段值(使用getter),然后基于修改后的值创建新对象,而不是使用setter方法简单地调整该对象的字段,这在语

我之前在阅读时看到以下引语:

“许多所谓的面向对象语言都有setter,当对象上有setter时,就可以将其转换回数据结构。”

文章继续暗示,这不是最佳实践,从长远来看可能会损害您开发的应用程序

我是一名CompSci学生,有C、Java、PHP、Ruby等方面的经验。。。因此,我对OOP作为一个概念和实践相当熟悉,但我绝不是一个专家

我想我的问题归结起来是: 在编写OO程序时,访问字段值(使用getter),然后基于修改后的值创建新对象,而不是使用setter方法简单地调整该对象的字段,这在语义上是否正确(也是一个最佳实践问题)

或者,如果我有一块木头,然后我从那块原始的木头上雕刻出一些木头,我应该把它建模为质量更小的同一块木头,还是一块全新的木头

使用setter看起来更简洁,如果您创建了这么多对象,那么垃圾收集将是一个问题,因此我从理论而不是实际的角度来处理这个问题


提前感谢您的回答

你在问两个问题:

1) 在对象中有公共字段可以吗

从维护/调试的角度来看,如果您至少出于一个原因通过方法访问对象的字段,通常会更好:该方法为字段的更改引入了一个公共条目,并且您可以添加自定义逻辑以防止无效更改,或者更新对象的不变量以保持其状态与请求的更改一致。如果对象中没有内部状态,则不需要方法(但仍然建议:它为所有调试访问引入一个断点区域)

2) 我应该使用可变对象还是不可变对象


这两种方法都是正确的。不可变对象允许更容易地对代码进行推理,因为您无法修改现有对象的状态。但是最终可能会有更多的对象,因此要么会使用更多的内存,要么垃圾收集器会有更多的工作。可变对象具有相反的优点/缺点

在我看来,这完全取决于您是否将所讨论的对象建模为“不可变”。根据您的模型,这可能非常有意义,在这种情况下,您应该避免对setter方法进行编码


但一般来说,我没有理由不使用setter。此外,您可以找到许多语言(C#,AS3),它们为定义setter方法提供了专门的语法

这完全取决于你想要实现什么。如果要更改实例的属性,应使用setter或类似方法(
carveOutSomeWood()
)。如果需要访问以前的版本并希望生成新实例,可以实现某种
createCopy()/clone()
方法来创建副本,然后将
carveOutSomeWood()
应用于该新实例

我不推荐通过读取旧实例的属性并自己创建来创建新实例。主要原因(可能还有其他原因)是,您的类可能会更改。然后还必须更改新实例的创建,因为它是在类之外完成的。如果只使用
createCopy()
方法,则类将负责解释其更改


您还可以直接引入一个
派生()
方法,该方法在内部创建副本并应用一些更改。

设置程序可能会暴露您的内部实现并导致一些问题。
如果您设置了一个对象,并根据新的分配状态执行了一些操作,那么如果外部更改了分配的对象,则可能会导致问题。

这是一个设计问题。面向对象的基本原理是封装。假设您有一个圆形对象。你可以有一个半径设定器和一个周长设定器。但当然,由于两者都链接在一起,因此设置周长也应该更改半径,而设置半径也应该更改周长。如果不是这样的话,您确实不再有对象,而是一个简单的数据结构,没有任何封装

现在有些对象是可变的,有些则不是。例如,字符串或整数是不可变的。一旦它有了一个值,它的值就不能改变。将一个字符串连接到另一个字符串只会创建一个新的字符串实例,而不会影响两个原始字符串中的任何一个。不可变对象更容易理解和使用,因为它们只有一种状态。它们本身也是线程安全的。但它们可能会导致性能问题。例如,在循环中串联会创建大量临时字符串实例,这些实例会消耗内存,必须进行GC’ed。这就是StringBuilder存在的原因:它基本上是一个可变字符串


总而言之:没有明确的答案,因为这完全取决于对象的种类和使用方式。一般来说,不可变对象比可变对象更受欢迎。喜欢变化较小的对象而不是变化较大的对象

一个对象必须至少有两种责任中的一种:行为和知识。行为定义了对象如何对其执行上下文中的事件做出反应,而知识定义了对象所知道的内容

行为被实现为方法,其中方法名称映射到触发反应的事件上。知识被实现为getter,它返回映射到被查询的Knowledge的值

以这种方式设计和实现的对象很少需要设置器,因为对象状态仅在对外部事件作出反应时才会改变。话虽如此,可以将外部事件作为设定器来实现(例如,car.setSpeed(…),但通常应寻求更合适的名称(例如,car.accelerateTo(…)和car.decreateto(…)