2012-12-10 229 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