V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
muziling
V2EX  ›  Kotlin

为啥类属性 Kotlin 要贬低 Java

  •  
  •   muziling · 2017-06-04 20:19:01 +08:00 · 8493 次点击
    这是一个创建于 2489 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如以下:
    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。
    实在不理解为啥这个地方要秀一下优越性。
    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   ·   我们的愿景   ·   实用小工具   ·   1137 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 18:34 · PVG 02:34 · LAX 11:34 · JFK 14:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.