我正在学习来自Java背景的Scala,并且我发现的第一件事情与Java的作品明显不同的是Enums。我试图通过反复试验完成我想要的一切,但我很想更好地理解我一路上正在做的事情。Enum.Value vs Enum#Value
从斯卡拉文档,我被告知通过扩展类Enumeration
创建一个枚举,并通过平等将它们设置为常数Value
增加值,例如:
object Label extends Enumeration{
val NONE = Value
}
这工作有关预期。我的麻烦来自于不仅使用枚举,而且使用自定义书写枚举扩展的扩展。我写了一段代码作为机器学习课程的一部分(现在已经结束),通过它们的标签分隔数据(例如用于TDIDT)。底部是它的一小部分,以便让我感到困惑。 Data
对象是可运行的,只是为了试用它。
首先,在打印语句,我认为这将是真实的,但它不是
println(Label.NONE.equals(MessageLabel.NONE))//Thought this would be true, is false
为什么会出现这种情况?即使MessageLabel继承的NONE
直接来自Label,类型系统坚持认为它们是不同的枚举值?
其次,更重要的是我已经Label.Value
和Label#Value
之间来回基本上慎之又慎。我贴有该版本:
def splitByLabel[T <: Label#Value]
trait Labelable[T <: Label#Value]
abstract class Data[T <: Label#Value]
class Message(... val label : MessageLabel.Value)
编译和运行正常。当我改变所有的#
s到.
,我上线splitByLabel(messages).foreach(a => println(a))
编译时错误,他说:
推断类型参数[MessageLabel.Value]不符合方法splitByLabel的类型参数界限[T <: Label.Value]
但是,当我改变所有的.
s到#
S,我上线class Message(val index : Int, val s : Map[Double, Int], override val label : MessageLabel#Value) extends Data[MessageLabel#Value](label)
编译时错误,他说:
未找到:类型MessageLabel
很明显,两者之间存在差异,它们各自填充特定角色。有人能帮助我理解有什么不同吗?谢谢!
/** Enum type all labels should extend. Guarantees access of universal NONE label */
class Label extends Enumeration{
val NONE = Value
}
/** Singleton instance for accessing NONE */
object Label extends Label{}
/** Companion object to all data classes. Hosts helper methods and a runnable main method */
object Data{
/** Returns a map of lists, each list is similarly labeled data. Map is label -> list of data */
def splitByLabel[T <: Label#Value](elms : List[Labelable[T]]) : Map[T, List[Labelable[T]]] = {
def f(acc : Map[T, List[Labelable[T]]], e : Labelable[T]) : Map[T, List[Labelable[T]]] = {
if(acc.contains(e.label)){
val l = acc(e.label)
acc - e.label + ((e.label, (e :: l)))
} else{
acc + ((e.label, List(e)))
}
}
elms.foldLeft(Map[T, List[Labelable[T]]]())(f)
}
def main(args : Array[String]){
println(Label.NONE.equals(MessageLabel.NONE))
val messages : List[Message] = (0 to 10).toList.map(a =>
new Message(a, Map(), if(a % 3 == 0) MessageLabel.HAM else MessageLabel.SPAM))
splitByLabel(messages).foreach(a => println(a))
}
}
/** Implementing classes can be labeled */
trait Labelable[T <: Label#Value]{
/** Returns the label of this thing */
val label : T
/** The possible labelings for this thing */
val labels : List[T]
}
abstract class Data[T <: Label#Value](override val label : T) extends Labelable[T]{
override def toString(): String = {
if (label != null)
label.toString
else
"NO_LABEL"
}
}
object MessageLabel extends Label{
val HAM, SPAM = Value
}
/** An instance represents a sentence. */
class Message(val index : Int, val s : Map[Int, Double], override val label : MessageLabel.Value)
extends Data[MessageLabel.Value](label){
/** Returns the possible labelings for a message */
override val labels = MessageLabel.values.toList
/** Adds index to tostring at front */
override def toString() : String = {
index + "-" + super.toString
}
}