我想使用抽象类型而不是类型参数。
在我的泛型类构造函数中,我想要一个泛型类型的参数,但代码不能编译:
class SomeOtherClass(val s: S){
type S
}
scala编译器错误“找不到:类型S”
如果我使用类型参数而不是抽象类型,那么它可以工作:
class SomeClass[T](val t: T){
//...
}
如果我想在构造函数中使用泛型参数,scala是否强制我使用类型参数而不是抽象类型?
还有其他办法吗?
答案 0 :(得分: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
答案 1 :(得分:1)
如果未指定抽象类型,则您的类需要是抽象的。所以你根本不需要参数。具有抽象类型的等价物将是:
abstract class SomeOtherClass {
type S
val s: S
}
然后在use-site:
val x = new SomeOtherClass {
type S = String
val s = "abc"
}
如果没有参数,这里的抽象类等同于特征。你最好使用特征,因为它的限制性较小(你只能扩展一个基类)。
答案 2 :(得分:0)
编译器应该如何知道应该使用哪种类型?您必须直接指定类型,这没有多大意义,或使用泛型。有一种方法可以使它发挥作用,但我认为它不会对你有所帮助。
class SomeClass(s: SomeClass#S) {
type S
}
但由于SomeClass#S未定义,因此没有实例。
答案 3 :(得分:0)
也许你想要这样的东西?通过这种方式,您可以拥有多个AbstractFooFactory
实例,每个实例生成Foo
s,并为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
答案 4 :(得分:0)
这里没有其他答案可以捕获用于这种情况的非常常见模式的两个部分,如下所示。我们为trait
使用abstract class
或SomeOtherClass
(如Luigi的回答),然后伴随对象的apply
方法是易于创建实例的工厂。它使用s
val,并且可以推断类型参数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)