可能使scala需要非Nothing通用方法参数并返回到类型安全性 [英] Possible to make scala require a non-Nothing generic method parameter and return to type-safety
问题描述
class Expression [+ T] //将有eval():T方法,所以+ T
class NothingTest {
def makey [T]():Expression [T] = null
$ b $ def needsBool(b:Expression [Boolean]):Unit = {}
var b:Expression [Boolean] = null
var n = makey()//:Expression [Nothing]
b = n // Yikes 。
needsBool(n)//: - / Supplied Expression [Nothing] ... not a Expression [Nothing]
}
我假设为 makey()
提供了一个类型参数。 makey [布尔型]()
),但是在这个例子中,我忘记了,编译的程序(顺便说一句,这非常容易)。 b
$ b
程序最终会在 needsBool
(省略实现)中失败,它没有收到表达式[Booolean]
object - 它得到了一个 Expression [Nothing]
对象。斯卡拉的文档说什么都不是所有类型的子类,这似乎是非常粗鲁的,并且无论它出现在哪里都肯定会打破类型安全。所以,为了重新引入一些类型安全性,我可以:
makey
返回Expression [Nothing],但要求提供类型参数? (我怀疑不),或者
needsBool
接收Expression [Nothing]?
更新:
更完整(编译,但是运行时失败的例子):
pre code> class Expression [+ T](val value:T){
def eval:T = value
}
class NothingTest {
def makey [T]():Expression [T] = new Expression [String] (b:Expression [Boolean]):Unit = {
val boolval = b.eval // Explode!字符串不是布尔值
println(boolval)
}
var b:Expression [布尔值] =空
var n = makey()//:表达式[没有]。你想提供一个类型,但忘记了。
b = n // Yikes。
needsBool(n)//: - / Supplied Expression [Nothing]
}
我发现了一个有点冒险的解决方案,但它的工作原理。
创建一个在其类型参数中是逆变的 NotNothing
类型,然后为 Any
提供一个隐式对象, 没有
。
现在,如果您尝试将 NotNothing
与 Nothing
一起使用,编译器会抱怨含糊不清。例子:
密封特质NotNothing [-T]
对象NotNothing {
隐式对象YoureSupposedToSupplyAType扩展了NotNothing [Nothing]
隐式对象notNothing extends NotNothing [Any]
}
然后用 NotNothing
类型限制你的 makey
函数:
def makey [T:NotNothing]()= {...}
现在如果你忘记提供一个类型,你会得到一个编译时错误!
In scala, the shit can hit the fan if the caller of a generic method omits to explicitly specify the type parameter. For example:
class Expression[+T] // Will have eval():T method, so +T
class NothingTest {
def makey[T](): Expression[T] = null
def needsBool(b: Expression[Boolean]): Unit = {}
var b: Expression[Boolean] = null
var n = makey() // : Expression[Nothing]
b=n // Yikes.
needsBool(n) // :-/ Supplied Expression[Nothing] ... not a Expression[Nothing]
}
I'm supposed to supply a type parameter to makey()
(e.g. makey[Boolean]()
), however in this instance I forgot, the program compiled (which, by the way, is extremely easy to do).
The program will eventually fail in needsBool
(implementation omitted) which did not receive an Expression[Booolean]
object - it got an Expression[Nothing]
object instead. Scala's docs says Nothing is a subclass of all types, which seems exceptionally rude and is certain to break type safety wherever it appears.
So, to reintroduce some type-safety, can I either:
- prevent
makey
from returning Expression[Nothing] but requiring that a type parameter be provided? (I suspect not), OR - prevent
needsBool
from receiving an Expression[Nothing]?
at compile-time.
Update:
A fuller (compiling, but runtime failing example):
class Expression[+T](val value:T){
def eval:T = value
}
class NothingTest {
def makey[T](): Expression[T] = new Expression[String]("blah").asInstanceOf[Expression[T]]
def needsBool(b: Expression[Boolean]): Unit = {
val boolval = b.eval // Explode! String is not a Boolean
println(boolval)
}
var b: Expression[Boolean] = null
var n = makey() // : Expression[Nothing]. You're suppose to supply a type, but forgot.
b=n // Yikes.
needsBool(n) // :-/ Supplied Expression[Nothing]
}
I've found a somewhat hacky solution, but it works.
Create a NotNothing
type that's contravariant in its type parameter, then provide an implicit object for both Any
and Nothing
.
Now if you try to use a value of NotNothing
with Nothing
the compiler will complain about ambiguity. Case in point:
sealed trait NotNothing[-T]
object NotNothing {
implicit object YoureSupposedToSupplyAType extends NotNothing[Nothing]
implicit object notNothing extends NotNothing[Any]
}
Then constrain your makey
function with the NotNothing
type:
def makey[T : NotNothing]() = { ... }
And voila now you'll get a compile time error if you forget to supply a type!
这篇关于可能使scala需要非Nothing通用方法参数并返回到类型安全性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!