我有一個返回Scala的映射值
[words: "one two", row: 23, col: 45]
在階餘上述更改爲階地圖但然後我不得不將其聲明爲
Map[String, Any]
一個函數(常規代碼)但其缺點是,如果我訪問的關鍵,如 地圖(「字」) 我要補充樣板
map2("words").asInstanceOf[String]
scala中有更好的方法,不需要我添加asInstanceOf嗎?
我有一個返回Scala的映射值
[words: "one two", row: 23, col: 45]
在階餘上述更改爲階地圖但然後我不得不將其聲明爲
Map[String, Any]
一個函數(常規代碼)但其缺點是,如果我訪問的關鍵,如 地圖(「字」) 我要補充樣板
map2("words").asInstanceOf[String]
scala中有更好的方法,不需要我添加asInstanceOf嗎?
爲了避免靜電打字鑄造和好處,你可以返回一個元組(String, Int, Int)
:
def getResult = ("one two", 23, 45)
val res = getResult
res._1 // the line
// alternatively use the extractor
val (line, row, _) = getResult // col is discarded
line // the line
row // the row
或使用的情況下,類結果:
case class MyResult(line: String, row: Int, col: Int)
def getResult = MyResult("one two", 23, 45)
val res = getResult
res.line // the line
// alternatively use the extractor provided by the case class
val MyResult(line, row, _) = getResult // col is discarded
line // the line
row // the row
我會更喜歡案例類,因爲這些字段是命名的,它實際上只是一行。
編輯:我已經瞭解到,您已經獲得了該地圖,並且需要一種更加乾淨的方式與其進行交互。當然,案例分析方法(如果適用)優於我在下面提出的方法。
如果你的鑰匙總是映射到相同的值類型,你可以做這樣的事情:
class TypedKey[T] {
def name = {
// assumes you declare only `object` instances
val simpleName = getClass.getSimpleName
val moduleName = if (simpleName.endsWith("$")) simpleName.substring(0, simpleName.size - 1) else simpleName
val lastDollar = moduleName.lastIndexOf('$')
if (lastDollar == -1) moduleName else moduleName.substring(lastDollar + 1)
}
}
object RubyKeys {
object words extends TypedKey[String]
object row extends TypedKey[Int]
object col extends TypedKey[Int]
}
class MapWrapper(val underlying: Map[String, Any]) {
def apply[T](key: TypedKey[T]) = underlying(key.name).asInstanceOf[T]
}
def main(args: Array[String]) {
val map = Map("words" -> "one two", "row" -> 23, "col" -> 45)
val wrapper = new MapWrapper(map)
import RubyKeys._
val w = wrapper(words) // String
val r = wrapper(row) // Int
val c = wrapper(col) // Int
println(w, r, c)
}
只有兩個可能的值類型,在你的榜樣將允許使用Either
類型與子類型Left
和Right
:
val m = Map("words" -> Left("one two"), "rows"-> Right(23), "cols"-> Right(45))
如果從地圖上得到一個值,你可以查看你所擁有的,例如與模式匹配或使用isLeft
和isRight
,並相應地「解開」它。
這是案例類是你的朋友。如果你的映射的鍵是大小寫類,那麼你可以強制客戶端代碼正確處理類型(並強制它正確處理所有類型)。
S:\>scala
Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> sealed abstract class Thing;
defined class Thing
scala> case class Toaster(slices: Int) extends Thing;
defined class Toaster
scala> case class Bucket(contents: String) extends Thing;
defined class Bucket
scala> val things = Map("toasty" -> Toaster(2), "buck" -> Bucket("stuff"));
things: scala.collection.immutable.Map[java.lang.String,Product with Serializable with Thing] = Map(toasty -> Toaster(2), buck -> Bucket(stu
ff))
scala> for (x <- things) x match {
case (k,Toaster(s)) => println(k + " " + s)
case (k,Bucket(c)) => println(k + " " + c)
}
toasty 2
buck stuff
這裏的關鍵是匹配語句正在破解各種情況,併爲您提供正確類型的變量以匹配其中的字段。通過聲明抽象類是封閉的,你讓編譯器知道它有所有可用的子類。有了這些信息,它可以告訴你什麼時候你失蹤了,還可以做進一步的優化。