0

我在Scala 中发现:不能在没有 getter 的情况下编写 setter?没有getter就无法创建setter:

对简单变量 x = e 赋值的解释取决于 x 的定义。如果 x 表示可变变量,则赋值将 x 的当前值更改为计算表达式 e 的结果。e 的类型应该符合 x 的类型。 如果 x 是在某个模板中定义的无参数函数,并且同一模板包含一个 setter 函数 x_= 作为成员,则赋值 x = e 被解释为该 setter 函数的调用 x_=(e )。 类似地,对无参数函数 x 的赋值 fx = e 被解释为调用 f.x_=(e)。赋值 f(args) = e 在 '=' 运算符左侧具有函数应用程序被解释为 f.update(args, e ) ,即调用由 f 定义的更新函数。

因此,不允许没有 getter 的 setter 是一个设计决定。但为什么?是更难实施还是根本不可能做到?

我确实有一个有效的用例,将它用作(有些复杂的)设置器,不使用这种语法糖会破坏项目中任何地方的相同语法。

4

1 回答 1

1

您可以尝试这样从您的 API 中排除访问者:

scala> class C { def c_=(i: Int) = println(i) ; private def c: Int = ??? }
defined class C

scala> val c = new C
c: C = C@289fdb08

scala> c.c = 42
<console>:14: error: method c in class C cannot be accessed in C
val $ires0 = c.c
               ^
<console>:12: error: method c in class C cannot be accessed in C
       c.c = 42
         ^

scala> def f = { c.c = 42 ; 0 }
<console>:12: error: method c in class C cannot be accessed in C
       def f = { c.c = 42 ; 0 }
                   ^

在第一个错误中,REPL 尝试使用访问器报告值。

这种成对的访问器和修改器的概念称为通用访问原则,因此被访问的成员看起来像一个属性。

表达式c.c必须在进一步去糖之前进行类型检查。否则,转换(对 的调用c.c_=)必须是纯语法的。

例如,提供扩展方法的隐式转换c_=可能会发挥作用。

于 2016-08-25T02:13:42.447 回答