实例化一个类';伴随对象中的s子类型';s在Scala中的应用方法
我一直在尝试使用一个伴随对象来实例化一个类的子类型。编译时不知道将实例化哪个子类。这与从第127页开始的Scala编程中的示例非常相似。我在这里设计了一个例子:实例化一个类';伴随对象中的s子类型';s在Scala中的应用方法,scala,apply,factory-pattern,subtype,companion-object,Scala,Apply,Factory Pattern,Subtype,Companion Object,我一直在尝试使用一个伴随对象来实例化一个类的子类型。编译时不知道将实例化哪个子类。这与从第127页开始的Scala编程中的示例非常相似。我在这里设计了一个例子: import scala.reflect.runtime.universe._ abstract class Animal class Dog extends Animal { def bark = "woof" } class Cat extends Animal { def meow = "meow" } object Ani
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反射文档,但它似乎非常密集和困难。此外,这似乎正是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 _ =>
}
}
这是不可能的
在第二个示例中,Animal.apply
始终返回Option[Animal]
,因为这是它的类型签名
你的对象测试
实际上是说,扩展了一点:
object Test extends App {
var dog: Option[Animal] = Animal.apply("dog")
println(dog.get.bark)
}
编译器可能能够在编译时判断它可能是一个
选项[Dog]
,但语言的语义不允许这样做:语法必须要复杂得多才能封装这些知识。这就产生了编译错误:`error:No TypeTag available for Option[This.Animal]`。您使用的是哪个版本的Scala?我已经安装了2.11.4。我将修改添加一个不使用反射的版本(并且由于类型问题而无法编译)。这听起来像是你在说,这不可能。是的,这是不可能的。你可以在运行时执行匹配
或isInstanceOf
来检查它的类型。。。但这不是你想要的,我想。我想知道这和Scala编程的例子有什么根本不同。127,本书不会调用仅在子类中的方法,而不会首先使用match
检查类型(如第128页的规范示例)。