你们用 get/set 吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
aqtata
V2EX    程序员

你们用 get/set 吗?

  •  
  •   aqtata 2021-06-08 15:05:01 +08:00 9241 次点击
    这是一个创建于 1594 天前的主题,其中的信息可能已经有所发展或是发生改变。
    getName()/setName(value)



    name()/name(value)

    你们习惯用哪种?
    58 条回复    2021-06-15 14:52:50 +08:00
    lllllliu
        1
    lllllliu  
       2021-06-08 15:06:03 +08:00
    getName()/setName(value)
    GeruzoniAnsasu
        2
    GeruzoniAnsasu  
       2021-06-08 15:08:41 +08:00   1
    除了 c++这种 snake_case 约定又没有 properties 写 name()来模拟它是个 property 外其它语言我其实想不到不加 get/set 的理由
    cking
        3
    cking  
       2021-06-08 15:09:54 +08:00   1
    看楼上两位的回答 我都不知道我自己用 java 的 lambda 默认的 get/set 是不是有问题了....
    Leviathann
        4
    Leviathann  
       2021-06-08 15:11:30 +08:00 via iPhone
    kotlin 里
    xx.name 就等于是 xx.getName()
    xx.name = "abc" 就等于是 xx.setName("abc")
    xiaomingVTEX
        5
    xiaomingVTEX  
       2021-06-08 15:21:15 +08:00
    get/set java pojo,
    可以看看极客时间 软件设计之美 14 面向对象之封装, 怎样的封装才算是高内聚
    3dwelcome
        6
    3dwelcome  
       2021-06-08 15:25:09 +08:00
    js 的 var a = this.name; 和 this.name = value;最好。

    反正 js 语言特性可以做到无感 hook,只有不支持的语言,才必须 set/get.
    kop1989
        7
    kop1989  
       2021-06-08 15:38:24 +08:00   1
    抛开语言来探讨这个问题其实是没意义的。
    楼上的回复也证明了,每种语言对于 getter 、setter 的理解与语法均不同。
    所以很难定义什么叫“用 get/set”。
    JamesR
        8
    JamesR  
       2021-06-08 15:42:22 +08:00
    这玩意麻烦得很,一两个人在开发的话,纯属多此一举,只有上百人那种大型项目各人写各人的类才有意义。
    nerocc
        9
    nerocc  
       2021-06-08 15:44:37 +08:00 via Android   4
    C#里面 field 和 property 是分得很清楚的两个概念,写起来舒服很多,不需要考虑这么多 get set 的问题
    Dockerfile
        10
    Dockerfile  
       2021-06-08 15:56:42 +08:00
    公司的项目用 getName()/setName(value)
    自己的用 name(),name(string name)来做 get/set
    Kasumi20
        11
    Kasumi20  
       2021-06-08 15:57:26 +08:00
    戴不戴套的问题
    ychost
        12
    ychost  
       2021-06-08 16:00:44 +08:00   4
    这一点 C# 的 {get;set;} 把 properties 和 field 分的命名白白,java 只能 @Getter @Setter 来释放劳动力了,很多的 JSON 序列化,ORM 都是基于 get_xxx 和 set_xxx 的名字,而不是 field 的名字
    Rwing
        13
    Rwing  
       2021-06-08 16:24:54 +08:00   21
    建议各位 java 程序员多睁开眼看看其他语言
    coderxy
        14
    coderxy  
       2021-06-08 16:28:22 +08:00
    最开始写 go 的时候就纠结要不要用 set get, 后来发现去 TMD,直接写不知道有多爽。 正常业务哪有那么多需要往后拓展的需求,实在变动大了基本就是重构了。
    Fule
        15
    Fule  
       2021-06-08 16:35:58 +08:00   3
    这方面 C# 的属性(Property)语法是真的香。

    **最传统的方式:**
    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
    abersheeran
        16
    abersheeran  
       2021-06-08 16:46:16 +08:00
    Python 直接 property

    c.k = v 就是 setter
    c.k 就是 getter
    iikebug
        17
    iikebug  
       2021-06-08 17:17:13 +08:00   1
    @Fule c#的语法真的不错
    xiaomingVTEX
        18
    xiaomingVTEX  
       2021-06-08 17:22:35 +08:00   1
    ## 摘录:14 | 面向对象之封装:怎样的封装才算是高内聚?

    封装的重点在于对象提供了哪些行为,而不是有哪些数据。也就是说,即便我们把对象理解成数据加函数,数据和函数也不是对等的地位。函数是接口,而数据是内部的实现,正如我们一直说的那样,接口是稳定的,实现是易变的。

    理解了这一点,我们来看一个很多人都有的日常编程习惯。他们编写一个类的方法是,把这个类有哪些字段写出来,然后,生成一大堆 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 语言,这就是一个很好的区分。能分清楚传输数据和业务对象,这就是一个很好的区分。
    lscexpress
        19
    lscexpress  
       2021-06-08 17:34:41 +08:00
    @Leviathann 在 php 里面也是
    3dwelcome
        20
    3dwelcome  
       2021-06-08 17:55:18 +08:00
    @xiaomingVTEX 现在 set/get 在 MVVM 中大量使用,框架可以在 set/get 上面下断点,知道变量什么时候被修改后,去通知与之关联的对象或事件。

    如果类似这个作者说的,把 setpassword 改成 changepassword,那 MVVM 框架,就没办法去监控这个类里的数据变化了。
    yejinmo
        21
    yejinmo  
       2021-06-08 20:00:15 +08:00
    public class CSharpIsTheBestLanguageInTheWorld
    {
    public string demo2 { get; private set; } = string.Empty;
    }
    xiaomingVTEX
        22
    xiaomingVTEX  
       2021-06-08 21:17:09 +08:00
    @3dwelcome #20 如果只是从 OOP 角度来说 get/set 是与对象的封装不符的,这样隐藏了对象的真实意图, 但是比如 java 中的 POJO 都有一个 get/set,引用下面的评论,POJO 作为了一种数据的载体,并不仅仅局限于对象的封装;
    另外, 类只是对象的一种表现形式(比如 java );再者也不是非要强制把 get/set 修改掉,毕竟只是一种编程范式
    wolfie
        23
    wolfie  
       2021-06-08 21:45:48 +08:00
    @Rwing
    对对对 封装是原罪,就不应该有设计模式
    yitingbai
        24
    yitingbai  
       2021-06-08 21:48:27 +08:00
    我有时候也挺纠结这个问题的, 最后还是发现写 get/set 跟直观一些, 代码提示更方便
    xingheng
        25
    xingheng  
       2021-06-08 22:02:47 +08:00
    @Fule #15 全篇我都同意,但是最后四个字符 YYDS 是什么臭狗屎
    tommyzhang
        26
    tommyzhang  
       2021-06-08 22:11:50 +08:00
    你写你的我写我的 我都不管你你管我呢?
    xingheng
        27
    xingheng  
       2021-06-08 22:17:56 +08:00
    @xiaomingVTEX #18 已经很少人能把 OO 讲清楚了。


    @3dwelcome #20 这和 MVVM 不冲突。
    xiaomingVTEX
        28
    xiaomingVTEX  
       2021-06-08 22:53:25 +08:00
    @xingheng #27 确实, 反正万物皆对象就行了, 哈哈
    walleL
        29
    walleL  
       2021-06-08 23:51:30 +08:00
    @xiaomingVTEX #18 相问下这段出处是哪里?
    wanguorui123
        30
    wanguorui123  
       2021-06-09 02:52:32 +08:00 via iPhone
    C# {get; set;,}
    JAVA @Data
    Rocketer
        31
    Rocketer  
       2021-06-09 06:45:41 +08:00 via iPhone
    其实 C#的 Property 默认写法与直接用 public 的变量没什么区别。以下两行几乎是一样的。
    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
        32
    xiaomingVTEX  
       2021-06-09 06:46:17 +08:00
    @walleL #29 极客时间 > 软件设计之美 > 14 | 面向对象之封装:怎样的封装才算是高内聚? > http://gk.link/a/10r9Q
    CodeCodeStudy
        33
    CodeCodeStudy  
       2021-06-09 09:12:44 +08:00
    因为 Java 的字段是不支持多态的,所以必须要用 getter/setter,不然容易出问题
    jorneyr
        34
    jorneyr  
       2021-06-09 09:12:46 +08:00
    Lombok 自动生成,需要的再手写覆盖,省事简洁还和手写代码效果一样。
    turingli
        35
    turingli  
       2021-06-09 09:19:23 +08:00 via Android   1
    @Fule C#10 public double Age{get;set=> field=Math.Round(value,2);} 进一步干掉字段
    ikas
        36
    ikas  
       2021-06-09 09:20:59 +08:00
    int _x,
    getX(){return _x}
    getY(){return 2_x+c.....}

    如果你只是简单的,无所谓,但是 get ,set 又不是只是 1:1 对应到字段,
    很多时候,set 方法还会做校验.
    上面说了一堆 c#,如果写 xaml ui,那 wm 里还要抛事件.set 也是必须的
    masterclock
        37
    masterclock  
       2021-06-09 09:54:00 +08:00
    scala "默认" 不可变,没有 set
    def 无参函数看起来就像是 val,不需要 get
    kahlkn
        38
    kahlkn  
       2021-06-09 10:05:12 +08:00
    @xiaomingVTEX 对于这位兄弟摘录的面向对象封装这块我觉得没有任何问题。

    但是如果到了具体的业务场景的时候,我觉得可以 分为 偏业务实体 和 偏数据实体。这位兄弟中的 setPassword 我觉得属于数据实体的范畴。而 changePassword 属于业务实体的范畴。并且这类业务实体,偏向充血模型(即将具体的业务行为放入到实体中)。本人作为 java 开发,java 中的实体偏向贫血模型(即实体更偏向于作为数据的载体,具体的业务行为不放入实体中)。

    至于 getter/setter 问题,反正 java 开发者必须写,除非你不打算用主流的框架。至于好处嘛,除了之前一位兄弟说的断点时可以监控外。 另外的作用就是 可以 在方法内 增加一些业务逻辑(尽管 java 中不建议这么做,但是对于一些紧急的需求修改上,可以临时的快速的搞搞,比如某个数据变形、裁切之类的,由于调用点很多一个一个改不方便,直接改 setter 中的内容,或者 getter 中的内容即可,前提评估好影响)。当然在 spring 等很多框架中,一些内部类或者包级别的类,可能有不少就直接 user.name 这样使用的。
    passerbytiny
        39
    passerbytiny  
       2021-06-09 10:14:00 +08:00 via Android
    用过一段时间的 name()/name(value),当然是用 lombok 自动生成的,到是挺喜欢这种用法,但是被 Jackson 等涉及到 Javabean 的工具打得头破血流,又改回去了。目前来说,大多数 Java 工具都遵循 Javabean 的 Getter/Setter 规范,虽然它们通过用手动配置的方式也能支持 name()/name(value)这种,但是基于约定优先与配置的敏捷开发思想,Java 这边还是老老实实的用 Getter/Setter (这种情况在慢慢改变,将来很有可能,在某个工具声明准备抛弃 Javabean 规范的很短时间内,Getter/Setter 就被主流工具迅速抛弃了)。


    @3dwelcome 你这个是声明式切面编程,只是可选约定,不是必须遵守的约定。这种声明式编程,有两个显著缺点:一、一刀切;二、依赖外部配置。故 Java 界自从注解出来后,就不再推荐甚至抛弃了。
    passerbytiny
        40
    passerbytiny  
       2021-06-09 10:33:46 +08:00 via Android
    Javabean 的原始定义可以在这里下载: https://www.oracle.com/java/technologies/javase/javabeans-spec.html 。这是 1997 年的定义,而且还是 Sun 的不是 JCP 的。

    需要纠正楼上的一些错误认识,Getter/Setter,或者说 JavaBean,是组件类,不是数据类。贫血领域模型这种名义上是业务类实际上是数据类的畸形结构,是 JavaBean 被滥用的表现,而不是 JavaBean 的表现。
    xiaomingVTEX
        41
    xiaomingVTEX  
       2021-06-09 10:46:51 +08:00
    贫血模型,充血模型, 学习了
    libook
        42
    libook  
       2021-06-09 11:45:32 +08:00
    是用属性还是方法,看需求。

    如果说命名的话,在可读性上还是推荐代码能体现谓语、名词原型和规模(一个还是一组),而这种体现可以直接写在名字里,也可以在调用路径上,比如 name.set(),当然 A.name='jake'语法上已经隐含了谓语。
    ericls
        43
    ericls  
       2021-06-09 12:45:53 +08:00 via iPhone
    这个工具解决什么问题
    你有没有遇到这个问题

    如果遇到 为什么不用?
    no1xsyzy
        44
    no1xsyzy  
       2021-06-09 13:02:36 +08:00
    (setf (car xxx) yyy) ( common lisp 系)?
    还是 (set-car! xxx yyy) ( scheme 系)?
    janda
        45
    janda  
       2021-06-09 16:30:38 +08:00
    lombok ?
    hikarugo
        46
    hikarugo  
       2021-06-09 17:18:09 +08:00
    兄弟你这个头像很复古,勾起了我十几年前的回忆
    crclz
        47
    crclz  
       2021-06-09 18:22:33 +08:00
    {get; set;}
    EthanZC
        48
    EthanZC  
       2021-06-09 18:48:02 +08:00
    case class 爽歪歪 scala 舒服
    pkoukk
        49
    pkoukk  
       2021-06-09 18:55:04 +08:00
    c# {get;set}
    go Name() SetName()
    ZhaoHuiLiu
        50
    ZhaoHuiLiu  
       2021-06-09 21:12:37 +08:00
    不明白,为什么 Java 获取字符串长度是 "test".length() 而不是 "test".getLength() 不觉得别扭吗?
    Fule
        51
    Fule  
       2021-06-09 21:38:27 +08:00
    @xingheng sorry, YYDS means 永远的神,毕竟近几个版本更新加入了很多使用 `=>`的语法,比如

    public int Add (int a, int b) => a + b;
    Fule
        52
    Fule  
       2021-06-09 21:45:19 +08:00
    说回来,对于楼主原始的问题,既然是用作一个方法(带括号调用),作为方法名,感觉还是带动词的名字比较合适:
    getName();
    setName("");
    JerryCha
        53
    JerryCha  
       2021-06-09 21:47:03 +08:00
    (() => ((() => SETvALUEwITHpARAMETER(name, value))(name))(value))()
    aoeui
        54
    aoeui  
       2021-06-09 22:14:06 +08:00 via Android
    Java: a.setValue(a.getValue() + 1);
    C#: a.Value++;
    tctc4869
        55
    tctc4869  
       2021-06-10 14:10:58 +08:00
    java 的 get/set 规比后来新生语言里的 set/get 规范差是肯定
    wangshanshan
        56
    wangshanshan  
       2021-06-10 17:48:12 +08:00
    @xiaomingVTEX 对于这个,理论上确实应该如此。可是在实际上,由于项目的中的对象各有不同,它所拥有的字段也各有不同,使用 get/set 可以通用于所有字段,如果给封装对象行为的名字 ,太过于独特
    Amit
        57
    Amit  
       2021-06-10 18:23:05 +08:00
    get/set 并不等价于获取 /设置变量值,里面是可以有逻辑的,比如前端传的一个非必填的参数,我可以在 get 方法里设置默认值(这不符合贫血模型但这种逻辑写到 service 中就太丑了),还有一些框架序列化或反序列化的时候使用 get/set 命名规则,不按这个来会出问题
    myCupOfTea
        58
    myCupOfTea  
       2021-06-15 14:52:50 +08:00
    java get/set 命名还不是早期不支持 proxy 吗,
    像 js,python 这种天生支持 get/set,还非要用 get/set 干嘛呢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1031 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 23:23 PVG 07:23 LAX 16:23 JFK 19:23
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86