以下哪项更好?它是基于意见还是有任何相关的差异?在某些情况下,是否可以选择其中一种?
public class MyClass {
private Integer myField;
public void setMyField(Integer myField) {
this.myField = myField;
}
public Integer getMyField() {
return myField;
}
}
我需要一种方法来检查是否允许某些东西。请不要谈论这个代码示例的意义。这只是一个很小的例子。
实施1
public boolean isAllowed() {
MyEnum.ALLOWED.getInt().equals(getMyField());
}
实施2
public boolean isAllowed() {
MyEnum.ALLOWED.getInt().equals(myField);
}
修改 这篇文章在链接问题中没有答案(见初始帖子的评论)
答案 0 :(得分:5)
以下哪项更好?它甚至是基于意见的还是 有任何相关的差异?可以选择其中一个或另一个 一些场景?
我认为这是良好做法的问题。不同之处在于代码的可读性。
作为一般规则,如果不需要,您应该避免间接。
MyClass
的当前实例具有其中一个字段中的信息以实现该操作。它不需要隐藏其内部状态。
因此在内部,MyClass
没有任何有价值的理由支持使用getMyField()
而不是直接使用myField
{1}}字段。
getMyField()
访问者更适合该类客户使用
所以我认为在你的示例代码中它总是更好:
public boolean isAllowed() {
MyEnum.ALLOWED.getInt().equals(myField);
}
修改:
除了可读性之外,这里有一个例子,说明为什么你没有兴趣将内部状态耦合到公共吸气剂
假设在开发阶段您从类中删除了public getMyField()
方法,因为对于类的客户端不再需要或不需要,如果isAllowed()
在其实现中依赖于getMyField()
,它将被打破,你应该用myField
替换它。
答案 1 :(得分:4)
我的回答不会是最有用的,但它会来自处理这种模式的直接经验。在设计对象时,通常很容易直接访问成员字段而不是依赖访问者。这种愿望源于想要简化对象并避免从简单返回值的方法中添加混乱。将您的示例更进一步添加上下文&意思是:
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;
}
}
这里的年龄是一个简单的数字,似乎没有必要在它周围添加getter / setter。如果我们添加以下方法,您将很想直接访问该字段,因为行为没有变化:
public Integer calculateScore() {
if(age > 21) return 100 - getNumberOfIncorrectAnswers();
//Add 10% before for younger students
else return (100 - getNumberOfIncorrectAnswers()) + 10;
}
然后,您的对象可以使用依赖于age字段的方法来增加新功能,您可以继续直接使用它。稍后,您可能会改变年龄的起源方式并从网络中提取价值。您可能不希望在构造函数中包含网络逻辑,因为它是一个昂贵的操作,只应根据需要触发。 calculateScore()
方法可以建立网络连接并发现年龄,但是所有其他依赖于年龄的方法也是如此。但是如果calculateScore看起来如下呢?:
public Integer calculateScore() {
if(getAge() > 21) return 100 - getNumberOfIncorrectAnswers();
//Add 10% before for younger students
else return (100 - getNumberOfIncorrectAnswers()) + 10;
}
然后,您可以在不触及calculateScore()
方法的情况下增强对象,从而更改其导出年龄的方式。这意味着您的方法遵循开放闭合原则(OCP)。它是开放的增强功能,但已关闭以进行更改,或者您无需更改方法源以更改它的年龄。
根据应用程序和对象模型的复杂程度,封装访问可能仍然有些过度,但即使在这些情况下,理解直接字段访问的权衡也是很好的,这些更简单的方案几乎是罕见的。
一般来说,您应该明白,封装的需求几乎不会立竿见影。随着对象的增长,它随着时间的推移而出现,并且如果对象从一开始就没有设置封装,那么将其逐步进入就更加昂贵。这就是使这种方法难以理解的原因。它需要经验(即,使得典型的过度简化并且在几年内遭受几次痛苦)才能感觉为什么封装是必要的。这不是你可以眼球和发现的东西。
也就是说,这曾经是一个比现在更大的问题,当时IDE并不是全功能的。今天,您可以在某些IDE(如IntelliJ)中使用内置的encapsulate fields
重构来根据需要引入模式。即使使用现代IDE,从一开始就实施封装仍然是有利的。
答案 2 :(得分:1)
我建议使用getter,因为在某些情况下,它可以有一些额外的逻辑(如格式化,检查空值等)。因此,在使用字段本身时,您可能会失去一些逻辑。
答案 3 :(得分:0)
为了保持良好的封装,首先想到你需要考虑的是你要在你的课外暴露哪些方法,如果在这里,例如你将只使用被允许的方法,我只会公开方法,并在构造函数中定义字段,如果该字段适合更改,那么您将需要getter / setter但总是取决于您希望从类中提供什么。并保持尽可能多的封装。
public class MyClass {
private Integer myField;
MyClass(Integer myField){
this.myField = myField;
}
//Only this method is offered nobody need to know you use myField to say true/false
public boolean isAllowed() {
MyEnum.ALLOWED.equals(myField);
}
}
答案 4 :(得分:-1)
在我的软件工程课程中,我被告知要实现秘密的原则"。因此,您应该始终使用getter和setter例程。这样,您可以确保没有人意外访问成员变量。
奇怪的函数或对象可能永远不会看到甚至更改成员变量,除非您通过setter和getter明确告诉他们这样做。
答案 5 :(得分:-1)
由于您的属性是私有的,因此您只能使用getter或setter方法在其他类中安全地访问它。所以我想说最好的实现是遵循封装原则的实现,即使用getter而不是直接访问的实现。 这也可以防止数据泄漏。