【问题标题】:Provide default type value for scala generic为 Scala 泛型提供默认类型值
【发布时间】:2015-09-09 04:58:26
【问题描述】:

我正在尝试使用 scala 类型类,但遇到了以下问题。我创建了一个具有多种方法的类。每个方法都有一个隐式参数 B 并返回一个 Either[A,B]。

B 类型是一个转换器,调用者可以在其中提供自定义对象以按照他需要的方式包装响应。

这里是代码

  case class A( var value:String){

  }

  case class Converter[A]( value : (Map[String, String] ) => A )

  object Converter{
     implicit val AConverter = new Converter[A]( (x:Map[String, String]) => new A("Hello World") )
     implicit val IntConverter = new Converter[Int]( (x:Map[String, String]) => 10 )
  }

  class API{

    def method1[B : Converter] : Either[A, B] = {
      Right( implicitly[Converter[B]].value(Map.empty))
    }

    def method2[B : Converter](name:String) : Either[A, B] = {
      Right( implicitly[Converter[B]].value(Map.empty))
    }

    def method3[B : Converter](id:Int) : Either[A, B] = {
      Right( implicitly[Converter[B]].value(Map.empty))
    }

  }

现在我的麻烦来了。我想归档关注

每个方法都应该是可调用的,而不用担心隐式参数 B 因为应该在某处定义一个默认实现。

所以我在伴生对象中定义了一些隐式,但这根本不能解决我的问题!

  // Works due implicit definiton
  println( new API().method1[A])
  // Works due implicit definiton
  println( new API().method1[Int])
  // Works not but should
  println( new API().method1)

我想说method1的B类型是Converter[A],method2的B类型是 Converter[Int] 如果调用者没有提供它。

  // Implementation should use my default Converter[A]
  println( new API().method1)

我在这里遇到了这个问题

https://stackoverflow.com/a/29205892/452265

如果类型本身没有像示例中那样传递给方法,那么我如何提供默认类型。我需要每个方法而不是每个类。

【问题讨论】:

  • 所以你想要一个默认类型参数?今天已经有人问过这个问题,答案已经在 SO 上。
  • 这是我发布的同一个链接,但这并不能解决我的问题:)
  • 为什么它不能解决你的问题?如果未提供默认类型,您是否希望提供默认类型?正确的?无论是类还是方法都没有关系。您可以在类级别或方法级别进行类型参数化。
  • 因为在那种情况下,人们会尝试初始化一个本地 var p:T,我想说如果没有给出隐式类型 B 应该是 Converter[一个]。看看代码不一样!

标签: scala generics type-inference


【解决方案1】:

这可能不是对问题的确切答案,而是针对您的问题的解决方案建议。

如果你想调用new API().method1,那么与其寻找指定默认类型参数的方法,不如定义一个没有类型参数的函数method1

case class A( var value:String){

}

case class Converter[A]( value : (Map[String, String] ) => A )

object Converter{
  implicit val AConverter = new Converter[A]( (x:Map[String, String]) => new A("Hello World") )
  implicit val IntConverter = new Converter[Int]( (x:Map[String, String]) => 10 )
}

class API{

  def method1: Either[A, A] = {
    Right(Converter.AConverter.value(Map.empty))
  }

  def method1[B : Converter] : Either[A, B] = {
    Right( implicitly[Converter[B]].value(Map.empty))
  }

  def method2[B : Converter](name:String) : Either[A, B] = {
    Right( implicitly[Converter[B]].value(Map.empty))
  }

  def method3[B : Converter](id:Int) : Either[A, B] = {
    Right( implicitly[Converter[B]].value(Map.empty))
  }

}

val undefined = new API().method1
val defined = new API().method1[Int]

这应该可以调用new API().method1。但是,有一些限制。例如。类型推断可能不会像预期的那样工作:

val defined: Either[A, Int] = new API().method1

不编译。

【讨论】:

  • 是的,我也这么认为
【解决方案2】:

我的想法和你一样,最后遇到了这个解决方案。它有点开销,但它似乎按我需要的方式工作!

class A(  val value:String){
     val success = true;
  }

  class B(  value:String) extends A(value){
     override val success = false;
  }

  class C(  override val value:String = "Doo") extends A(value){
     override val success = false;
  }

  case class Converter[A]( value : (Map[String, String] ) => A ){

  }

  object Converter{
     implicit lazy val method1Converter  = new Converter[B]( (x:Map[String, String]) => new B("foo") )
     implicit lazy val method2Converter  = new Converter[C]( (x:Map[String, String]) => new C() )
  }

  trait method1Impl{

    def method1 : Either[A, B] = {
      Right( Converter.method1Converter.value( Map.empty ) )
    }

    def method1[B : Converter] : Either[A, B] = {
      Right( implicitly[Converter[B]].value(Map.empty))
    }
  }

  trait method2Impl{

    def method2 : Either[A, C] = {
      Right( Converter.method2Converter.value( Map.empty ) )
    }

    def method2[B : Converter]( name:String) : Either[A, B] = {
      Right( implicitly[Converter[B]].value(Map.empty))
    }
  }

  class API extends method1Impl with  method2Impl {



  }


  // Works not but should
  println( new API().method1)

  println( new API().method2[C]("Hello"))

【讨论】:

    猜你喜欢
    • 2015-08-21
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 2022-08-05
    • 2020-10-07
    • 2019-01-02
    相关资源
    最近更新 更多