11

我想使用抽象类型而不是类型参数。

在我的泛型类构造函数中,我想要一个泛型类型的参数,但代码无法编译:

class SomeOtherClass(val s: S){
    type S
}

scala 编译器错误是“未找到:类型 S”

如果我使用类型参数而不是抽象类型,那么它可以工作:

class SomeClass[T](val t: T){
    //...
}

如果我想在构造函数中使用泛型参数,scala 是否会强制我使用类型参数而不是抽象类型?

还有另一种方法可以做到这一点吗?

4

5 回答 5

3

在这种情况下,您几乎被迫使用泛型类型参数。您可以通过在类之外声明类型来解决它,但是您需要实例化包装器,然后实例化对象,它会很快变得丑陋。

trait FooDef {
  type T
  class Foo(val x: T)
}
val ifd = new FooDef { type T = Int }
val ifoo = new ifd.Foo(5)
val sfd = new FooDef { type T = String }
val sfoo = new sfd.Foo("hi")
def intFoos(f: fd.Foo forSome { val fd: FooDef {type T = Int} }) = f.x + 1
于 2012-08-07T12:03:37.137 回答
1

当未指定抽象类型时,您的类需要是抽象的。所以你根本不需要这个参数。抽象类型的等价物是:

abstract class SomeOtherClass {
  type S
  val s: S 
}

然后在使用现场:

val x = new SomeOtherClass {
  type S = String
  val s = "abc"
}

没有参数,这里的抽象类就相当于一个trait。最好使用特征,因为它的限制较少(您只能扩展一个基类)。

于 2012-08-07T17:14:34.760 回答
0

编译器应该如何知道它应该在那里使用什么类型?要么您必须直接指定类型,这没有多大意义,要么使用泛型。有一种方法可以使它工作,但我认为它不会帮助你。

class SomeClass(s: SomeClass#S) {
  type S
}

但是由于 SomeClass#S 没有定义,所以没有它的实例。

于 2012-08-07T11:59:45.347 回答
0

也许你想要这样的东西?这样,您可以有多个实例,AbstractFooFactory每个生产Foos 具有不同的 s 值。

trait AbstractFooFactory {
  type S
  def makeFoo(s:S):Foo
  class Foo(val s:S) {}
}

object StringFooFactory extends AbstractFooFactory {
  override type S = String
  override def makeFoo(s:String) = new Foo(s)
}

val b = StringFooFactory.makeFoo("bar")
val s:String = b.s
于 2012-08-07T12:02:56.730 回答
0

这里的其他答案都没有捕获用于这种情况的非常常见模式的两个部分,如下所示。我们使用 atrait或 an abstract classSomeOtherClass如 Luigi 的回答),然后伴随对象的apply方法是轻松创建实例的工厂。它接受sval 并且S可以推断类型参数,这简化了在我们使用它的任何地方实例化对象。

trait SomeOtherClass {
  type S
  val something: S 
}

object SomeOtherClass {
  def apply[S0](s:S0) = new SomeOtherClass {
    type S = S0
    val something = s
  }
}

// usage
SomeOtherClass(12)
于 2018-06-27T01:14:52.223 回答