Oop 避免setter更改类的值';s属性
我有一个带有一个私有字段的类:Oop 避免setter更改类的值';s属性,oop,encapsulation,setter,getter-setter,Oop,Encapsulation,Setter,Getter Setter,我有一个带有一个私有字段的类: class Person { string name; public void setName(string name); } 然后,使用负责与用户交互的某个对象(在本例中是通过命令行),我想更改此字段的值: Person somePerson; CommandLineView view; somePerson.setName(view.askUserForName()); 它起作用了。但是我不喜欢使用set函数,因为它会暴露类成员。 因此,我开始考虑
class Person {
string name;
public void setName(string name);
}
然后,使用负责与用户交互的某个对象(在本例中是通过命令行),我想更改此字段的值:
Person somePerson;
CommandLineView view;
somePerson.setName(view.askUserForName());
它起作用了。但是我不喜欢使用set
函数,因为它会暴露类成员。
因此,我开始考虑如何避免它
新的实现如下所示:
class Person
{
string name;
public void changeName(view) { name = view.askUserForName(); }
}
以及:
现在Person
不公开其成员。此外,此类负责与更改名称相关的逻辑(例如,函数changeName
还可以更新数据库、通知相关方等)
问题是:这种重构是一种好的实践吗?或者使用
setter
实现更好,即使它破坏了封装?我认为根本不应该有方法来设置名称,它应该是一个构造函数参数:
Person somePerson(view.askUserForName());
您的方法存在的问题是,您首先创建的对象没有完全初始化,因此使用它是危险的:Person somePerson
。如果您忘记了设置名称
,您的代码还会与这个“空”人一起工作吗
然后允许直接用setName
方法修改内部状态,这也不好
使用构造函数参数可以避免这两个问题
至于最初的问题——我不认为这两种方法之间有太大的区别。
结果完全相同-您调用该方法并且内部对象状态已更改。您可以将其命名为setName
或changeName
,结果相同
使用changeName(view)
的第二种方法实际上更糟糕,因为还引入了Person
对view
对象的依赖关系。
现在,如果你想更改名称,你总是需要先创建
视图
对象。不知道这个问题是否适合这里-但我认为你现在使用它的方式确实将人
方式与命令行视图
紧密结合起来-最好有一个setter或只是一个更改名称
方法(取新名称)-视图取决于模型是可以的(显然)但另一个方向是一个巨大的警告标志!你为什么不想公开姓名?@Carsten-那么你认为在person
和view
之间插入一个新层怎么样,例如一些演示者?@SimonWood-公开私有字段不被认为是一种代码气味吗?在我看来p之间几乎没有区别public
字段和private
一个带有setter和/或getter的字段。为什么要使用另一个间接层?我想你会想在模型和视图中使用演示者-因此你会让视图依赖于模型和演示者,演示者依赖于模型和视图…什么都没有得到-抱歉,我只是不知道是什么你不想要接吻设定者^^-这是一种符合我品味的创业方式。软件中可以存在没有名字的人!例如,我可以代表我从窗口看到的人-我对他们的外表了解很多,但只有在打开窗口并提出要求后我才能知道他们的名字;)但这不是讨论的重点。我同意,也许依赖于视图是不好的。也许它应该依赖于像NameChanger
这样的东西。我读过一篇Yegor Bugayenko的文章:我遵循这句话:“一个对象可以被其他对象撕裂,因为它们可以通过setter将任何新数据注入其中。该对象无法足够安全地封装自己的状态,因为任何人都可以更改它。”这里的关键字是“安全”-我相信只允许指定的对象更改Person
的状态有助于避免一些错误。@PiotrAleksanderChmielowski我认为你是在欺骗自己,想找到一种奇特的方法来为一个名字设置一个setter,而这篇文章说的是你应该完全避免设置setter。这里有一句话:狗是一个不可变的生命体,它不允许外界的任何人改变它的体重、大小、名字等。
。基本上,如果您有任何形式的getter和setter,这与将name
字段声明为public
:person->name=“New name”
是一样的。看起来不好吗?基本上,如果你有一个getter和setter,以任何形式,这就等同于将提交的名称声明为公共“我同意!但是我不认为在我的问题的changeName(view)
中有一个隐藏的setter
。name
的值正在Person
类中更改。它不是从外部更改的。@PiotrAleksanderChmielowski,但随后有人更改了view=newcommandlineview(“新名称”);人员->更改姓名(视图)代码>,如果这是可能的,那么您实际上有一个setter。
Person somePerson(view.askUserForName());