在某些方法中,我想强制命名参数。原因是自动生成的代码,其参数的顺序未指定(并将保持这种方式)。
我能得到的最接近的是
private val _forceNamed: Object = new Object()
def doSomething(forceNamed: Object = _forceNamed, arg1: String, arg2: String, ...): Unit = {
if (forceNamed != _forceNamed) {
throw Exception(something)
}
// actually do stuff
}
然而,这只会在运行时失败,而在编译时失败的东西会更好。
答案 0 :(得分:3)
如果你想要关闭能够传递null
的漏洞,你可以使用一个值类作为守卫。
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Foo {
import Foo._
def foo(x: Bar = bar, a: String, b: String) = println(a + b)
}
object Foo {
private[Foo] class Bar(val i: Int) extends AnyVal
private val bar = new Bar(42)
}
// Exiting paste mode, now interpreting.
defined class Foo
defined object Foo
scala> val f = new Foo
f: Foo = Foo@4a4f9c58
scala> f.foo(null, "", "")
<console>:13: error: type mismatch;
found : Null(null)
required: Foo.Bar
f.foo(null, "", "")
^
答案 1 :(得分:2)
这样的事情可能是:
class Foo {
class Bar private[Foo]()
private val bar = new Bar
def foo(x: Bar= bar, a: String, b: String) = println(a + b)
}
答案 2 :(得分:2)
为此我们在代码库中有这个:
object `(Please use explicitly named arguments)`
def foo(
`(Please use explicitly named arguments)`:
`(Please use explicitly named arguments)`.type =
`(Please use explicitly named arguments)`,
namedArg1: Int,
namedArg2: String,
...
) = ...
答案 3 :(得分:1)
多么好主意。
看起来默认args的卫生问题禁止单身类型。
$ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> private val x = new Object ; def f(foo: x.type = x, i: Int) = i
<console>:11: error: private value x escapes its defining scope as part of type x.type
private val x = new Object ; def f(foo: x.type = x, i: Int) = i
^
scala> val x = new Object ; def f(foo: x.type = (x: x.type), i: Int) = i
x: Object = java.lang.Object@1e54cb33
f: (foo: x.type, i: Int)Int
scala> f(i = 42)
<console>:13: error: type mismatch;
found : Object
required: x.type
f(i = 42)
^
或者不,这看起来不错:
private[this] val x: Object = new java.lang.Object();
<stable> <accessor> def x: Object = $iw.this.x;
def f(foo: x.type = $iw.this.x, i: Int): Int = i;
<synthetic> def f$default$1: x.type = $iw.this.x
或问题是分配到默认值?
但你不能这样做:
scala> val x: x.type = new Object
<console>:36: error: recursive value x needs type
val x: x.type = new Object
^
我想这很有效,因为你不必告诉它x
是x.type
:
scala> object x
defined object x
scala> def f(y: x.type = x, i: Int) = i
f: (y: x.type, i: Int)Int
scala> f(i = 42)
res2: Int = 42
这仍然允许明确提供x
,这可能会被混淆。
我太害怕调查失败的原因了:
scala> object x$$ ; def f(y: x$$.type = x$$, i: Int) = i
defined object x$$
f: (y: .type, i: Int)Int
scala> f(i = 42)
res0: Int = 42
scala> f(x$$, 42) // or x$$$
<console>:13: error: not found: value x$$
f(x$$, 42)
^
但这表明即使对象是公开的,对它的访问也会因名称损坏而瘫痪。
答案 4 :(得分:0)
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102).
Type in expressions for evaluation. Or try :help.
scala> type `(Please use explicitly named arguments)` = Nothing
defined type alias $u0028Please$u0020use$u0020explicitly$u0020named$u0020arguments$u0029
scala> def foo(`(Please use explicitly named arguments)`: => `(Please use explicitly named arguments)` = ???, i: Int, j: Int) = i + j
foo: ((Please use explicitly named arguments): => (Please use explicitly named arguments), i: Int, j: Int)Int
scala> foo(null, 1, 4)
<console>:13: error: type mismatch;
found : Null(null)
required: (Please use explicitly named arguments)
(which expands to) Nothing
foo(null, 1, 4)
^
scala> foo(i = 1, j = 4)
res1: Int = 5