到目前为止的搜索结果使我相信,如果没有非主要构造函数,这是不可能的
class Foo { // NOT OK: 2 extra lines--doesn't leverage Scala's conciseness
private var _x = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
或牺牲主要构造函数中的参数名称(丑陋地使用命名参数进行调用)
class Foo(private var _x: Int) { // OK: concise
def x = _x
}
val f = new Foo(_x = 123) // NOT OK: named parameter should be 'x' not '_x'
理想情况下,可以执行以下操作:
class Foo(private var x: Int) { // OK: concise
// make just the getter public
public x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
我知道命名参数在Java世界中是一门新事物,因此对大多数人来说可能并不那么重要,但是来自命名参数更为流行的语言(Python),此问题立即出现。
所以我的问题是:这可能吗? (可能不是),如果没有,为什么(在我看来)这种重要的用例在语言设计中却没有被发现?通过这种方式,我的意思是代码必须牺牲简洁的命名或简洁的定义,这是Scala的标志。
P.S. 考虑一种情况,在突然将公共(public)场所设为私有(private)的同时将获取者保持公开状态,在这种情况下,开发人员必须更改1行并添加3行才能在保持接口(interface)相同的同时达到效果:
class Foo(var x: Int) {} // no boilerplate
->
class Foo { // lots of boilerplate
private var _x: Int = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
最佳答案
这是否确实是设计缺陷还值得商.。人们会认为,使语法复杂化以允许这种特定用例是不值得的。
同样,Scala毕竟是一种主要的函数式语言,因此程序中不应该经常使用var,这再次引发了一个问题,即是否需要以特殊方式处理这个特殊用例。
但是,看来您的问题的简单解决方案是在伴随对象中使用apply
方法:
class Foo private(private var _x: Int) {
def x = _x
}
object Foo {
def apply(x: Int): Foo = new Foo(x)
}
用法:
val f = Foo(x = 3)
println(f.x)
之后编辑:
这是一种与您最初请求的解决方案类似的解决方案,但是会稍微改变命名:
class Foo(initialX: Int) {
private var _x = initialX
def x = _x
}
用法:
val f = new Foo(initialX = 3)