scala只有类可以声明但未定义的成员

时间:2012-08-30 10:03:02

标签: scala scala-collections

  def random[T](array: Array[(T, Double)]): T = {
    var total: Double = 0
    array.foreach(x => total += x._2)

    if (total > 1)
      throw new IllegalArgumentException("The total ratio shouldn't greater than 1.")

    val ratio = rand.nextDouble()
    var min: Double = 0
    var max: Double = 0

    var theOne:T = null // error here !!!

    array.foreach {
      x =>
        max += x._2
        if (ratio > min && ratio <= max)
          theOne = x._1

        min += x._2
    }

    theOne
  }

如何避免此问题?

3 个答案:

答案 0 :(得分:2)

您可以使用选项类型:

  def random[T](array: Array[(T, Double)]): Option[T] = {
var total: Double = 0
array.foreach(x => total += x._2)

if (total > 1)
  throw new IllegalArgumentException("The total ratio shouldn't greater than 1.")

val ratio = rand.nextDouble()
var min: Double = 0
var max: Double = 0

var theOne:Option[T] = None

array.foreach {
  x =>
    max += x._2
    if (ratio > min && ratio <= max)
      theOne = Some(x._1)

    min += ratio
}

theOne
}

匹配表达式

def show[T](x: Option[T]) = x match {
 case Some(s) => s
 case None => null
}

val res = random...
show(res)

答案 1 :(得分:1)

这里的问题是你没有保证null是类型T的有效值.Scala的类型层次结构是这样开始的。

任何

AnyVal extends Any //不能为null

AnyRef extends Any //可以为null

因为你没有以任何方式约束类型T,所以它不能保证T不是anyval的子类(如Int或Double),因此不能允许你赋值null。一个简单的解决方案是将_替换为_,如此...

class Container[T] {
    var t: T = _
}

这将使Scala编译器用适当的T默认值替换_(引用类型为null)。

答案 2 :(得分:0)

我想要快速代码,不要使用foreach。否则,您可以执行以下操作以与第二个元组元素成比例绘制:

def random[T](array: Array[(T, Double)]): T = {
  val cumulative = array.scanLeft(0d)(_ + _._2)
  val pick = rand.nextDouble() * cumulative.last

  array.
var min: Double = 0
var max: Double = 0

var theOne:T = null // error here !!!

array.foreach {
  x =>
    max += x._2
    if (ratio > min && ratio <= max)
      theOne = x._1

    min += ratio
}

theOne

}