如何使用对象&x27;参数化类;s类型在Scala中获取它的实例?

如何使用对象&x27;参数化类;s类型在Scala中获取它的实例?,scala,generics,parameterization,Scala,Generics,Parameterization,我想用对象类型参数化一个类,使我的代码更通用。通过这样做,我不需要为扩展某个特性的所有对象实现 我有以下代码来说明我的目标: abstract trait Foo { def greet } object Coo extends Foo { def greet = println("Coo!") } object Boo extends Foo { def greet = println("Boo!") } class A[Fooer <: Foo] { def mo

我想用对象类型参数化一个类,使我的代码更通用。通过这样做,我不需要为扩展某个特性的所有对象实现

我有以下代码来说明我的目标:

abstract trait Foo {
  def greet
}

object Coo extends Foo {
  def greet = println("Coo!")
}

object Boo extends Foo {
  def greet = println("Boo!")
}

class A[Fooer <: Foo] {
  def moo = asInstanceOf[Fooer].greet()
}

object Main extends App {
  new A[Coo.type].moo() // hopefully prints "Coo!"
}
我相信这是因为
asInstanceOf
调用似乎在隐式地使用
this

本质上我的问题是:如何通过参数化在类中按类型获取对象的实例

我相信这是因为
asInstanceOf
调用似乎在隐式地使用
this

Scala中的每个类都扩展了
Any
,该类继承了特殊方法
asInstanceOf
,以及其他内容。我不会说它是隐式发生的——只是调用了该类的一个成员方法,而该类是在自身上调用它。与您编写的
def moo=greet
相同

此外,任何时候使用
作为
的替代,都是在要求编译器对自己撒谎并继续进行。这通常会导致
ClassCastException
。在本例中,这是因为您试图将实例
A
强制转换为
Foo
的某个未知子类型。这是行不通的。在非常具体的情况下,您试图将单例类型
Coo.type
传递给
A
的实例,然后创建
Coo.type
的新实例。虽然有很多其他原因导致这不起作用,但其中一个原因是不能创建单例类型的第二个实例——之所以称之为单例实例是有原因的

更一般地说,您不知道可以简单地构造给定类型的对象。类型没有构造函数,类有

这可能是简化示例的一个副作用,但是您需要使用一些类型参数创建
a
的实例,而不需要将其传递给实际对象,但是您所关心的对象已经存在。那为什么不通过呢

class A[Fooer <: Foo](f: Fooer) {
  def moo = f.greet
}
然而,这是粗糙的。首先,它不适用于上面的单例类型(因为它们无法再次构造)。第二,我们只能在没有构造函数参数提供的情况下调用
newInstance
,并且无法强制执行

因此,尽管这会起作用:

scala> class Bar extends Foo { def greet = print("Bar") }

scala> new A(classOf[Bar]).moo
Bar
以下内容不会:

scala> class Baz(i: Int) extends Foo { def greet = println("Baz") }
defined class Baz

scala> new A(classOf[Baz]).moo
java.lang.InstantiationException: Baz

scala> new A(classOf[Coo.type]).moo
<console>:14: error: class type required but Coo.type found
       new A(classOf[Coo.type]).moo
                        ^

回答得很好。我希望避免经过构造函数,但我想这是最好的方法。非常感谢您抽出时间回答!您还可能会发现这一点:
scala> class Bar extends Foo { def greet = print("Bar") }

scala> new A(classOf[Bar]).moo
Bar
scala> class Baz(i: Int) extends Foo { def greet = println("Baz") }
defined class Baz

scala> new A(classOf[Baz]).moo
java.lang.InstantiationException: Baz

scala> new A(classOf[Coo.type]).moo
<console>:14: error: class type required but Coo.type found
       new A(classOf[Coo.type]).moo
                        ^
trait FooBuilder[A] {
    def build(): A
}

implicit object BarBuilder extends FooBuilder[Bar] {
    def build() = new Bar
}

class A[Fooer <: Foo](implicit fb: FooBuilder[Fooer]) {
    def moo = fb.build().greet
}