首页 文章

scala类构造函数和抽象类型

提问于
浏览
11

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

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

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

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

如果我使用类型参数而不是抽象类型,那么它的工作原理如下:

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

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

还有另一种方法吗?

5 回答

  • 0

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

    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
    
  • 3

    如果未指定抽象类型,则您的类必须是抽象的 . 所以你根本不需要参数 . 具有抽象类型的等价物将是:

    abstract class SomeOtherClass {
      type S
      val s: S 
    }
    

    然后在使用现场:

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

    没有参数,这里的抽象类等同于特征 . 你最好使用特征,因为它的限制性较小(你只能扩展一个基类) .

  • 0

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

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

    但由于SomeClass#S未定义,因此没有实例 .

  • 0

    也许你想要这样的东西?通过这种方式,您可以拥有 AbstractFooFactory 的多个实例,每个实例生成具有不同s值的 Foo .

    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
    
  • 1

    这里没有其他答案捕获用于这种情况的非常常见模式的两个部分,如下所示 . 我们使用 traitabstract class 作为 SomeOtherClass (因为Luigi 's answer) and then the companion object' s 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)
    

相关问题