我一直在尝试使用伴生对象来实例化一个类的子类型。在编译时不知道将实例化哪个子类。这与从第 127 页开始的Programming Scala中的示例非常相似。我在这里设计了一个示例:
import scala.reflect.runtime.universe._
abstract class Animal
class Dog extends Animal { def bark = "woof" }
class Cat extends Animal { def meow = "meow" }
object Animal {
def apply(specify: String): Option[Animal] = {
specify match {
case "dog" => Some(new Dog)
case "cat" => Some(new Cat)
case _ => None
}
}
}
object Test extends App {
def getType[T: TypeTag](obj: T) = typeOf[T]
var dog = Animal("dog")
println(getType(dog))
}
这个程序打印出来scala.Option[Animal]
。我希望它打印出来scala.Option[Dog]
。此外,如果我尝试将该行添加println(dog.bark)
到对象的末尾Test
,则无法编译。这根本不可能吗?
我一直在研究 Scala 反射文档,但它似乎非常密集和困难。此外,这似乎正是Programming Scala示例的工作原理,所以我无法想象我在这里做错了什么。
编辑:这个版本没有反射,只是由于类型错误而引发编译时错误。
abstract class Animal
class Dog extends Animal { def bark = "woof" }
class Cat extends Animal { def meow = "meow" }
object Animal {
def apply(specify: String): Option[Animal] = {
specify match {
case "dog" => Some(new Dog)
case "cat" => Some(new Cat)
case _ => None
}
}
}
object Test extends App {
var dog = Animal("dog")
println(dog.get.bark)
}
// $ scalac test.scala
// test.scala:17: error: value bark is not a member of Animal
// println(dog.get.bark)
// ^
// one error found
编辑:显然这需要模式匹配才能解决。这是一个工作示例,有些简化。
abstract class Animal
class Dog extends Animal { def bark = "woof" }
class Cat extends Animal { def meow = "meow" }
object Animal {
def apply(specify: String): Animal = {
specify match {
case "dog" => new Dog
case "cat" => new Cat
}
}
}
object Test extends App {
val dog = Animal("dog")
dog match {
case d: Dog => println(d.bark)
case _ =>
}
}