首页 > 解决方案 > 如何从类型中提取类型参数

问题描述

给定以下类:

abstract class Foo[B] 
abstract class Baz[B, F <: Foo[B]] {
    def get(foo: F): B
    // other methods
} 

Baz我讨厌当第一个是多余的时我需要两个类型参数。我想写一些类似的东西:

abstract class Baz[F <: Foo[B]] {
  def get(foo: F): B
}

我是否可以在不采用多个类型参数的情况下在 Baz 中引用(F 的)B 类型?这感觉应该是可能的,但我似乎无法弄清楚语法。

标签: scalagenericstypes

解决方案


  1. 您可以B创建类型成员而不是类型参数吗?

    abstract class Foo { type B }
    abstract class Baz[F <: Foo] {
      def get(foo: F): F#B
      // other methods
    }
    

    然后,如果您需要类型参数和类型成员,则可以使用 Aux-pattern

    abstract class Foo { type B }
    // Foo.Aux[B] instead of Foo[B]
    object Foo {
      type Aux[B0] = Foo { type B = B0 }
    }
    abstract class Baz[F <: Foo] {
      def get(foo: F): F#B
      // other methods
    }
    
  2. 你能做出F更高种类和get多态的吗?(看起来有点像“无标签最终”方法。)

    abstract class Foo[B]
    abstract class Baz[F[X] <: Foo[X]] {
      def get[B](foo: F[B]): B
      // other methods
    }
    
  3. 你能做Foo一个类型类吗?

    abstract class Foo[F] {
      type B
    }
    object Foo {
      type Aux[F, B0] = Foo[F] { type B = B0 }
      def instance[F, B0]: Aux[F, B0] = new Foo[F] { type B = B0 }
    
      //instead of  class F1 extends Foo[B1]
      implicit val foo1: Aux[F1, B1] = instance
    }
    
    abstract class Baz[F](implicit val foo: Foo[F]) {
      def get: foo.B
      // other methods
    }
    

    或者

    abstract class Baz[F: Foo] {
      val foo: Foo[F] = implicitly
      def get: foo.B
      // other methods
    }
    
  4. 你能把这两个类型参数提取到一个新的类吗?

    abstract class Foo[B]
    
    abstract class Tuple {
      type B
      type F <: Foo[B]
    }
    
    abstract class Baz[T <: Tuple] {
      def get(foo: T#F): T#B
      // other methods
    }
    

    或者

    abstract class Baz[T <: Tuple](t: T) {
      def get(foo: t.F): t.B
      // other methods
    }
    

推荐阅读