为啥类属性 Kotlin 要贬低 Java - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
muziling
V2EX    Kotlin

为啥类属性 Kotlin 要贬低 Java

  •  
  •   muziling 2017-06-04 20:19:01 +08:00 9316 次点击
    这是一个创建于 3118 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如以下:
    public class Person {
    var name: String = ""
    }
    ...
    val person = Person()
    person.name = "name"
    val name = person.name
    Kotlin 教程总要说 Java 傻,要用 getter 和 setter,Java 把 name 定义成 public,照样不需要 getter 和 setter。
    实在不理解为啥这个地方要秀一下优越性。/div>
    28 条回复    2017-06-06 16:28:15 +08:00
    wwqgtxx
        1
    wwqgtxx  
       2017-06-04 20:23:48 +08:00 via iPhone
    能问出这个问题就能充分体现出你根本没有弄懂 getter 和 setter 存在的必要性
    cwek
        2
    cwek  
       2017-06-04 20:34:23 +08:00
    同不知道 getter,setter 的重要性

    不过 Java 有 IDE 自动生成的话,这个算是 IDE 的糖?
    yuhuan66666
        3
    yuhuan66666  
       2017-06-04 20:42:52 +08:00 via Android
    同不懂,求大神解释
    muziling
        4
    muziling  
    OP
       2017-06-04 20:45:10 +08:00
    @wwqgtxx #1
    没理解,如果要说是用来保护成员变量,这个例子 Kotlin 也是完全放开读写的。
    如果要说 set 来做自己的逻辑,比如
    public void setSpeed(int speed) {
    if ( speed > 100 ) {
    this.speed = 100;
    } else {
    this.speed = speed;
    }
    }

    那其实 Kotlin 也需要写这段代码
    public classs XXX{
    set(value){
    field = if (speed > 100) 100 else speed;
    }
    }
    xupefei
        5
    xupefei  
       2017-06-04 20:51:14 +08:00
    getter 和 setter 的意义在于可以在赋值的同时做一些其它的事,例如

    ```
    getXXX {
    xxx = value;
    DoSomeWork();
    }
    ```

    Java 上倒是有个 Project Lombok,可以给 变量加 @Getter 和 @Setter 自动生成相应的方法。
    xupefei
        6
    xupefei  
       2017-06-04 20:55:09 +08:00
    @xupefei 说白了还是 C# 好,可以直接写

    public string XXX {
    ....get=>_xxx;
    ....set {
    ........_xxx=value;
    ........DoSomething();
    ....}
    }
    sagaxu
        7
    sagaxu  
       2017-06-04 21:02:38 +08:00   9
    你没 get 到
    https://kotlinlang.org/docs/reference/properties.html

    Java 定义成了 public,就绕过 getter/setter 了,如果有 100 个地方写了 foo.bar = xxx,你把 field 改成 private 再加上 getter/setter 的时候,已经晚了,你要 100 个地方一个个改过来,如果你发布的是个库,所有使用这个库的代码都要一一改过来。

    Kotlin 的 property,你写 foo.bar=xxx 的时候,它会检查有没有 setter,有 setter 就会调用 setter,没有就直接赋值。因为 property 定义的时候,是可以有可选的 getter/setter 的。当你给一个 property 增加 setter 的时候,调用它的地方,是不需要修改代码的。C#或者 Python 都有这样的特性,只有万年不变的 Java 一直原地踏步。
    searene
        8
    searene  
       2017-06-04 21:04:50 +08:00
    据我所见,很多情况下 class 里面的 getter 和 setter 都只有一行代码,跟直接把字段暴露为 public 没有什么区别,但很多人还是习惯直接生成 getter 和 setter。
    hyperdak288
        9
    hyperdak288  
       2017-06-04 21:10:27 +08:00
    话说这个特性不是 groovy 早就有了么,为什么也能吹一波?
    Sharuru
        10
    Sharuru  
       2017-06-04 21:20:07 +08:00   1
    Lombok 多好用……管那么多
    Kotlin 这种四不像语言……

    嘛,黑 Java 反正 P.C.
    geelaw
        11
    geelaw  
       2017-06-04 21:23:55 +08:00 via Android
    原因里面最显然的一个:get/set 可以 override,一个公有字段不能。

    再举一个例子:并不是所有的属性都有一个成员和它对应,例如一个代表 Windows 窗口的类,它的成员可能只有一个 handle,设置、获取窗口标题是通过 API 完成的。
    royzxq
        12
    royzxq  
       2017-06-04 22:58:01 +08:00
    js 瑟瑟发抖
    DCjanus
        13
    DCjanus  
       2017-06-05 00:40:11 +08:00
    @searene 为了将来可能的修改啊,而且 Java 的很多框架都是依赖 set 和 get 方法做反射
    linux40
        14
    linux40  
       2017-06-05 09:29:57 +08:00 via Android
    其实也就长得不一样,其它没区别。
    bk201
        15
    bk201  
       2017-06-05 09:30:03 +08:00 via iPhone
    那应该问为什么用 private
    silva
        16
    silva  
       2017-06-05 10:13:55 +08:00
    @sagaxu 如你所说的话,我觉得这是个很蠢的特性呢?
    同样是看到一句 aa.b = xx 的赋值语句,我需要看上下文才知道这是一句直接的赋值还是调用了 setter 函数。

    这类看似简便,实则引入混乱的语法糖最让人讨厌了
    af463419014
        17
    af463419014  
       2017-06-05 10:45:58 +08:00
    @sagaxu @silva
    我也认为 kotlin 提供的这个语法糖是一个得不偿失的改进,为了代码上的精简,导致了语义的不清晰
    如果整个团队都熟悉 kotlin 还好
    但是对于大多数普通的开发人员,只会让代码变得难以理解

    虽然 java 的 getter,setter 需要很多冗余的代码,但是 ide 里提供了快捷键添加,实际开发中并不会耽误我们时间
    mooncakejs
        18
    mooncakejs  
       2017-06-05 11:49:30 +08:00
    @af463419014 setter 如果作为方法调用其实影响最大的是链式操作
    a.xx = b.yy = c.zz = value
    如果是 setter 就要
    a.setXX(value)
    b.setYY(value)
    sagaxu
        19
    sagaxu  
       2017-06-05 12:07:46 +08:00
    @silva 你不需要看上下文,你可以当作它就是调用了 setter,赋值只是它的优化,优化时省略了自动合成的 setter 而已。即便是 Java 写了 setter,你不看代码,仍然不知道它是不是只做了赋值,还是做了别的事情。你创建的对象,JVM 也会做优化,有的在堆上,有的在栈上,通过逃逸分析和 JIT 等优化手段,它有很多种可能性,你在 Java 里写的 getter/setter,JVM 仍然存在帮你把方法调用优化掉的可能性,所以你关心是真的赋值还是 set 方法,毫无意义。

    @af463419014 不熟悉 kotlin,熟悉 Python 或者 C#也行,即便 JS 也有这个功能,property 是很多现代语言的共性,并不会增加多少理解上的困难。Kotlin property 能做的事情远非 getter/setter 这么简单,它还能很方便的实现 lazy 求值。事实上很多 Javaer 已经开始用 Lombok 去自动合成 getter/setter,IDE 的确能比手写省事不少,但是一个 300 行的文件,跟一个 100 多行的文件,每次读到多出来的 100 多行代码会占用大脑几个 cycle,有时还要多拖动两下,降低效率。
    silva
        20
    silva  
       2017-06-05 13:49:57 +08:00
    @sagaxu 你这个解释是站不住脚的。这里的问题是在语法上混淆了简单赋值和函数调用,这不是你在逻辑上如何想这个问题就算了的。
    两个不同的事情,用同样的语法来表示,就是一种混淆不清。这个地,我感觉没得洗。

    至于你说 JAVA 优化的问题,跟这个问题无关
    mko0okmko0
        21
    mko0okmko0  
       2017-06-05 15:22:37 +08:00
    假设一个任务,同样的注解量,
    kotlin 写只要 java 的 50%就能完成,并且性能达到 java 的 90%,
    但性能要达到 java 的 95%就要写 120%以上,
    你选用哪一个?

    然后你不觉得这个问题很熟吗?
    我举例 JPEG 压缩,在品质 75%以下过去 20 年有多少新格式能体积性能都赢它?

    JPEG 有太多问题,但它还是市场覆盖率选择率最高的影像储存格式,没有之一.

    再例如 php 这个全世界最好的破烂玩意,依旧是 web 界最优选择之一.

    所以能用 1 行语法完成功能,谁愿意写 10 行?

    再说,"你要语意清晰很简单,该类用 java 写好,用 kotlin 去呼叫该 java 档案就好了",
    kotlin 从来没有要取代 java 过,其他的 JVM 语言我还觉得更有取代的念头.

    所以到底有什么好争议的,
    我还是浪费生命写了一篇回文,感觉自己蠢
    sagaxu
        22
    sagaxu  
       2017-06-05 15:34:27 +08:00
    @silva 你当然有权认为这是混淆,但是 C#,Swift,Python,Ruby,PHP,JS,VB 等等都是这么做的,这已经是比较 common 的 sense 了,也许 Java10 或者 Java11 也会引入这样的特性,你接受不了可以不用。哦,顺便说一下,即使是 Java6,用了注解,也会有一些改变语义的 magic 发生,是不是也是种混淆?还有==运算符,有时候比的是引用,有时候比的是值,你也别用了。
    sagaxu
        23
    sagaxu  
       2017-06-05 15:35:50 +08:00   1
    @mko0okmko0 Koltin 性能 >= Java,得益于 inline 方法
    silva
        24
    silva  
       2017-06-05 19:04:57 +08:00
    @sagaxu 也就是说你已经承认这个确实是混淆语义的设计。但是这个垃圾特性分布非常广,让人无法回避呗。

    我有个不太相关的问题,上面你一连举了那么多语言都包含该特性,不会是想用数量来说明正确性吧?
    silva
        25
    silva  
       2017-06-05 19:16:19 +08:00
    @sagaxu 算了,这特性也不是你加进去的。保留各自观点吧
    sagaxu
        26
    sagaxu  
       2017-06-05 19:54:58 +08:00
    @silva 对你来说是语义混淆,对我来说那是增强,它不会给我造成任何不清晰或者不明确,相反会节约我时间。

    数量跟正确性无关,但是一大波主流语言的设计者们的共同选择,正确的可能性还是蛮高的。

    从根本上说,是否加入 XX 特性可能无关正确性,而是各人根据自身经验和喜好,做的一个决定罢了。

    ps: 从某种程度上讲,interface 和多态,是同类型同签名方法的不同语义,也是一种你眼中的混淆,只不过你没法回避这种混淆,只能认命。
    silva
        27
    silva  
       2017-06-06 10:05:20 +08:00
    @sagaxu 你既然继续认为数量既是正确性(概率),那也没啥好说的。

    PS:可惜做的最灵活的 C++,在实际项目上没有相对“死板” JAVA 应用范围广。其中原因自然也不是你可以理解的。

    至于认不认命的你想多了,都不值得上技术手段。
    sagaxu
        28
    sagaxu  
       2017-06-06 16:28:15 +08:00
    @silva C++这样也能算最灵活?估计你没玩过 lisp 吧。一个语言流行不流行,有很多因素在里面,灵活不灵活只是很小的一个因素之一。你觉得死板是优点,你高兴就好。不喜欢死板的 Javaer,已经用上 Lombok 了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3203 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 11:29 PVG 19:29 LAX 03:29 JFK 06:29
    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