你们用 get/set 吗?
source link: https://www.v2ex.com/t/782167
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
和
name()/name(value)
你们习惯用哪种?
GeruzoniAnsasu 1 天前 1
3dwelcome 1 天前
ychost 1 天前 4
Fule 1 天前 3
**最传统的方式:**
private int _score = 10;
public int Score
{
get
{
// potential more logic here
return _score;
}
set
{
// potential more logic here
_score = value;
}
}
**简化方式(无默认值)**
public int Score { get; set; }
**简化方式(有默认值)**
public int Score { get; set;} = 10;
**简化方式只读属性**
public int Score { get; private set; }
public int Score { get; }
**简化方式只读属性带默认值**
public int Score => 10;
题外话,C#里 `=>` YYDS
xiaomingVTEX 1 天前 1
封装的重点在于对象提供了哪些行为,而不是有哪些数据。也就是说,即便我们把对象理解成数据加函数,数据和函数也不是对等的地位。函数是接口,而数据是内部的实现,正如我们一直说的那样,接口是稳定的,实现是易变的。
理解了这一点,我们来看一个很多人都有的日常编程习惯。他们编写一个类的方法是,把这个类有哪些字段写出来,然后,生成一大堆 getter 和 setter,将这些字段的访问暴露出去。这种做法的错误就在于把数据当成了设计的核心,这一堆的 getter 和 setter,就等于把实现细节暴露了出去。
一个正确的做法应该是,我们设计一个类,先要考虑其对象应该提供哪些行为。然后,我们根据这些行为提供对应的方法,最后才是考虑实现这些方法要有哪些字段。
封装的重点在于对象提供了哪些行为,而不是有哪些数据。也就是说,即便我们把对象理解成数据加函数,数据和函数也不是对等的地位。函数是接口,而数据是内部的实现,正如我们一直说的那样,接口是稳定的,实现是易变的。理解了这一点,我们来看一个很多人都有的日常编程习惯。他们编写一个类的方法是,把这个类有哪些字段写出来,然后,生成一大堆 getter 和 setter,将这些字段的访问暴露出去。这种做法的错误就在于把数据当成了设计的核心,这一堆的 getter 和 setter,就等于把实现细节暴露了出去。一个正确的做法应该是,我们设计一个类,先要考虑其对象应该提供哪些行为。然后,我们根据这些行为提供对应的方法,最后才是考虑实现这些方法要有哪些字段。
```
class User {
private String username;
private String password;
...
// 修改密码
public void setPassword(final String password) {
this.password = password;
}
}
```
但我们鼓励的做法是,把意图表现出来:
```
class User {
private String username;
private String password;
...
// 修改密码
public void changePassword(final String password) {
this.password = password;
}
}
```
这两段代码相比,只是修改密码的方法名变了,但二者更重要的差异是,一个在说做什么,一个在说怎么做。将意图与实现分离开来,这是一个优秀设计必须要考虑的问题。
不过,在真实的项目中,有时确实需要暴露一些数据,所以,等到你确实需要暴露的时候,再去写 getter 也不迟,你一定要问问自己为什么要加 getter 。至于 setter,首先,大概率是你用错了名字,应该用一个表示意图的名字;其次,setter 通常意味着修改,这是我们不鼓励的。
## 评论区
* 沧浪之水:
至于平时说的一些 POJO 的对象,可以看成是数据载体,是可以加 getter,setter 的(没有这些默认的 getter,setter,很多第三方的数据转化都很不方便,比如 json,sql 等)。在使用的时候,不归结为对象就可以了。
* 作者回复: 能分清楚面向对象和 Java 语言,这就是一个很好的区分。能分清楚传输数据和业务对象,这就是一个很好的区分。
3dwelcome 1 天前
如果类似这个作者说的,把 setpassword 改成 changepassword,那 MVVM 框架,就没办法去监控这个类里的数据变化了。
yejinmo 1 天前
{
public string demo2 { get; private set; } = string.Empty;
}
xiaomingVTEX 1 天前
另外, 类只是对象的一种表现形式(比如 java );再者也不是非要强制把 get/set 修改掉,毕竟只是一种编程范式
Rocketer 18 小时 12 分钟前 via iPhone
public int SomeProperty {get; set;} = 10;
public int someField = 10;
区别在于,当你需要对值做一些处理时,比如:
private int _someField = 10;
public int SomeProperty
{
get
{
return _someField;
}
set
{
if (value >= 10)
{
_someField = value;
}
}
}
对外部来说,用法是统一的,还是 object.SomeProperty = 15;
而 Java 正好相反,为了让外部的用法统一,把原本可以直接 public 的变量也封装进了 getter/setter 方法中。
xiaomingVTEX 18 小时 11 分钟前
turingli 15 小时 38 分钟前 via Android 1
ikas 15 小时 36 分钟前
getX(){return _x}
getY(){return 2_x+c.....}
如果你只是简单的,无所谓,但是 get ,set 又不是只是 1:1 对应到字段,
很多时候,set 方法还会做校验.
上面说了一堆 c#,如果写 xaml ui,那 wm 里还要抛事件.set 也是必须的
kahlkn 14 小时 52 分钟前
但是如果到了具体的业务场景的时候,我觉得可以 分为 偏业务实体 和 偏数据实体。这位兄弟中的 setPassword 我觉得属于数据实体的范畴。而 changePassword 属于业务实体的范畴。并且这类业务实体,偏向充血模型(即将具体的业务行为放入到实体中)。本人作为 java 开发,java 中的实体偏向贫血模型(即实体更偏向于作为数据的载体,具体的业务行为不放入实体中)。
至于 getter/setter 问题,反正 java 开发者必须写,除非你不打算用主流的框架。至于好处嘛,除了之前一位兄弟说的断点时可以监控外。 另外的作用就是 可以 在方法内 增加一些业务逻辑(尽管 java 中不建议这么做,但是对于一些紧急的需求修改上,可以临时的快速的搞搞,比如某个数据变形、裁切之类的,由于调用点很多一个一个改不方便,直接改 setter 中的内容,或者 getter 中的内容即可,前提评估好影响)。当然在 spring 等很多框架中,一些内部类或者包级别的类,可能有不少就直接 user.name 这样使用的。
passerbytiny 14 小时 43 分钟前 via Android
@3dwelcome 你这个是声明式切面编程,只是可选约定,不是必须遵守的约定。这种声明式编程,有两个显著缺点:一、一刀切;二、依赖外部配置。故 Java 界自从注解出来后,就不再推荐甚至抛弃了。
passerbytiny 14 小时 24 分钟前 via Android
需要纠正楼上的一些错误认识,Getter/Setter,或者说 JavaBean,是组件类,不是数据类。贫血领域模型这种名义上是业务类实际上是数据类的畸形结构,是 JavaBean 被滥用的表现,而不是 JavaBean 的表现。
libook 13 小时 12 分钟前
如果说命名的话,在可读性上还是推荐代码能体现谓语、名词原型和规模(一个还是一组),而这种体现可以直接写在名字里,也可以在调用路径上,比如 name.set(),当然 A.name='jake'语法上已经隐含了谓语。
Fule 3 小时 19 分钟前
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK