2012-12-10 225 views
4

我想從函數返回一個類型。例如:斯卡拉 - 返回類型

class Super 
case class One(a: Int) extends Super 
case class Two(b: Float) extends Super 
case class Unknown extends Super 

def decide(criterion: String): ??? = { 
    criterion match { 
    case "one" => One 
    case "two" => Two 
    case _ => Unknown 
    } 
} 

所以我想返回類型本身,將其存儲在一張地圖,這樣我可以某處後應用它:

val test = Buffer(
    ("ahaha" -> "one") 
    ("ohoho" -> "two") 
    ("lalala" -> "one") 
) 

var map = scala.collection.mutable.Map[String, Super]() 

test.map {pair => 
    map(pair._1) = decide(pair._2) 
} 

這樣,以後我會想:

def act(code: String) { 
    map(code) match { 
    case One => doSmth[One]() 
    case Two => doSmth[Two]() 
    case _ => doNothing() 
    } 
} 

我知道某些部件,像案例類的未使用的參數在這裏可能看起來很奇怪,但這是它在我工作的環境中的樣子,這個例子是完整的,因爲我不確定是否它會我不同,如果我拿走東西...

那麼我怎樣才能使decide函數返回一個類型,然後以類似於我所顯示的方式使用它?

+0

你可能會用'classOf' java.lang.Class中(如classOf [一])的函數方法,以便返回類型將是' java.lang.Class [Super]' –

+0

@ om-nom-nom工作了一半。仍然我無法將返回的類型作爲類型參數傳遞給'doSmth'方法... – noncom

+0

這與確定返回的內容並沒有什麼關係,但爲什麼要在這裏使用地圖呢?爲什麼不相反只是傳遞函數'決定'? – drstevens

回答

4

我想你可能想要case object One等,而不是使用Class或ClassTag。然後你得到有用的匹配支持。對於act方法,您的案例對象可能會返回一個ClassTag或類似的,或者只是讓行爲關聯一個與doSmth [OneClass]等。

看起來你可以讓你的案例伴侶進入案件對象。不是那麼特別

package typeswitch 
import reflect.runtime.universe._ 

sealed trait Selection 

class Super 
case class One(a: Int) extends Super 
case object One extends Selection 
case class Two(b: Float) extends Super 
case object Two extends Selection 
case class Unknown() extends Super 
case object Unknown extends Selection 

object Test extends App { 
    type What = Selection 

    def decide(criterion: String): What = criterion match { 
    case "one" => One 
    case "two" => Two 
    case _ => Unknown 
    } 

    val test = List(
    "ahaha" -> "one", 
    "ohoho" -> "two", 
    "lalala" -> "one" 
) 

    val m = scala.collection.mutable.Map[String, What]() 

    test map (pair => m(pair._1) = decide(pair._2)) 

    def act(code: String) = m(code) match { 
    case One => doSmth[One]() 
    // non-exhaustive 
    //case Two => doSmth[Two]() 
    case Unknown => doNothing() 
    // handle exhaustively 
    case s: Selection => doSmthNew(s) 
    } 
    def doSmthElse[A <: Super]()(implicit t: TypeTag[A]): A = { 
    Console println s"Do st with $t" 
    val claas: Class[_] = t.mirror.runtimeClass(t.tpe) 
    null.asInstanceOf[A] 
    } 
    def doSmth[A <: Super]()(implicit t: ClassTag[A]): A = { 
    Console println s"Do st with $t" 
    val claas: Class[_] = t.runtimeClass 
    null.asInstanceOf[A] 
    } 
    def doSmthNew[A >: What : ClassTag, B <: Super](what: A): B = { 
    Console println s"Do st new with $what" 
    null.asInstanceOf[B] 
    } 
    def doNothing() { } 

    val res = act("lalala") 
    Console println s"Got $res?" 
} 
+0

嗯,一個不錯的嘗試,我想的是類似的東西..但這實際上是一個後備 - 解決方案假設沒有直接使用類型本身 - 它使用伴侶對象,在這種情況下,命名整型常量..但是,我想不出在這裏更好......也許JVM不會讓我們做我需要的東西..... – noncom

+1

你要找的詞是「漂亮」。它不是命名常量,因爲你對匹配進行了詳盡的檢查,並且通過反射很容易獲得伴隨類。你不會在doSmth中顯示你想要做的。 –

+0

現在我明白了!對,可能這是最好的.. – noncom

3

很抱歉,如果這是太基本的,但:

$ scala 
Welcome to Scala version 2.10.0-RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_06). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> trait Bar 
defined trait Bar 

scala> case class Foo(i:Int) extends Bar 
defined class Foo 

scala> import reflect.runtime.universe._ 
import reflect.runtime.universe._ 

scala> def f[A <: Bar : TypeTag]() = println(s" Do ${ implicitly[TypeTag[A]] }") 
f: [A <: Bar]()(implicit evidence$1: reflect.runtime.universe.TypeTag[A])Unit 

scala> f[Foo] 
Do TypeTag[Foo] 
+0

嗯,這對我來說不是基本的,我會研究這個,謝謝! – noncom