可能使scala需要非Nothing通用方法参数并返回到类型安全性 [英] Possible to make scala require a non-Nothing generic method parameter and return to type-safety

查看:78
本文介绍了可能使scala需要非Nothing通用方法参数并返回到类型安全性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在scala中,如果通用方法的调用者忽略显式指定类型参数,那么shit可以击中风扇。例如:

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆