Chr*_*311 4 java oop coding-style
以下哪项更好?它是基于意见还是有任何相关的差异?在某些情况下,是否可以选择其中一种?
public class MyClass {
private Integer myField;
public void setMyField(Integer myField) {
this.myField = myField;
}
public Integer getMyField() {
return myField;
}
}
Run Code Online (Sandbox Code Playgroud)
我需要一种方法来检查是否允许某些东西.请不要谈论这个代码示例的意义.这只是一个很小的例子.
实施1
public boolean isAllowed() {
MyEnum.ALLOWED.getInt().equals(getMyField());
}
Run Code Online (Sandbox Code Playgroud)
实施2
public boolean isAllowed() {
MyEnum.ALLOWED.getInt().equals(myField);
}
Run Code Online (Sandbox Code Playgroud)
编辑: 此帖子在链接问题中没有答案(请参阅初始帖子的评论)
以下哪项更好?它是基于意见还是有任何相关的差异?在某些情况下,是否可以选择其中一种?
我认为这是良好做法的问题.不同之处在于代码的可读性.
作为一般规则,如果不需要,您应该避免间接.当前实例MyClass
具有其中一个字段中的信息来实现操作.它不需要隐藏其内部状态.
所以在内部,MyClass
没有任何有价值的理由支持getMyField()
使用该myField
领域的直接使用.
的getMyField()
存取器更适合于由类的客户端使用.
所以我认为在你的示例代码中它总是更好:
public boolean isAllowed() {
MyEnum.ALLOWED.getInt().equals(myField);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
除了可读性之外,这里有一个例子,为什么你没有兴趣将内部状态耦合到公共getter.
假设在开发阶段你从类中删除了public getMyField()
方法,因为对于类的客户端不再需要或不需要,如果isAllowed()
依赖getMyField()
于它的实现,它将被破坏,你应该替换它myField
.
我的回答将不是最有用的,但是它将来自处理这种模式的直接经验。设计对象时,通常很想直接访问成员字段而不是依赖访问器。需求源于希望简化对象并避免简单返回值的方法增加混乱。让您的示例更进一步以添加上下文和含义:
public class MyClassmate {
private Integer age;
public MyClassmate(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
}
Run Code Online (Sandbox Code Playgroud)
这里的年龄是一个简单的数字,似乎没有必要在其周围添加吸气剂/设置剂。如果我们添加以下方法,由于行为没有变化,您将很容易直接访问该字段:
public Integer calculateScore() {
if(age > 21) return 100 - getNumberOfIncorrectAnswers();
//Add 10% before for younger students
else return (100 - getNumberOfIncorrectAnswers()) + 10;
}
Run Code Online (Sandbox Code Playgroud)
然后,您的对象可能会使用依赖于您继续直接使用它的age字段的方法来扩展新功能。稍后,您可能会更改年龄的生成方式,并从整个网络中提取该值。您可能不希望将网络逻辑包含在构造函数中,因为这是一项昂贵的操作,应仅在需要时才触发。该calculateScore()
方法可以建立网络连接并发现使用期限,但是其他所有依赖于使用期限的方法也都可以。但是,如果calculateScore如下所示,该怎么办?:
public Integer calculateScore() {
if(getAge() > 21) return 100 - getNumberOfIncorrectAnswers();
//Add 10% before for younger students
else return (100 - getNumberOfIncorrectAnswers()) + 10;
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以增强对象,从而改变其推算年龄的方式,而无需触碰该calculateScore()
方法。这意味着您的方法遵循开放式封闭原则(OCP)。它可以进行增强,但不能更改,或者您不必更改方法的来源即可更改使用期限。
根据您的应用程序和对象模型的复杂性,有时仍然会出现封装访问过高的情况,但是即使在这些情况下,也应该了解直接字段访问的权衡,而这些更为简单的情况很少见。
通常,您应该了解几乎不需要封装。随着对象的增长,它会随着时间的流逝而出现,如果从一开始就没有使用封装来设置对象,则逐步引入它的成本会更高。这就是这种方法难以理解的原因。需要经验(即进行典型的过度简化并在数年内遭受多次折磨)才能感觉到为什么需要封装。这不是您可以察觉和发现的东西。
就是说,这比现在的IDE还不具备全部功能时要大得多。今天,您可以encapsulate fields
在某些IDE(如IntelliJ)中使用内置的重构,以根据需要引入模式。即使使用现代IDE,从一开始就实践封装仍然是有利的。