【问题标题】:Scala - define a trait with generic methodsScala - 使用泛型方法定义特征
【发布时间】:2016-02-29 22:14:21
【问题描述】:

如何在其方法中定义带有泛型参数的特征,然后用特定类型的参数覆盖?

一个例子:

import shapeless._

case class UserA(name:String)
case class UserB(name:String)

trait User {
  def save(item:Option[T]): Option[T]
}
class UserAdmin extends User {
  def save(item:Option[UserA]): Option[UserA]
}
class UserSomethingElse extends User {
  def save(item:Option[UserB]): Option[UserB]
}

有了这个,我得到了错误not found: type T,即使它是在 shapeless 中定义的

【问题讨论】:

  • 我认为您可能会将“通用编程”(这是无形的)与“参数多态性”混淆,这似乎是您在这个问题中所关心的。我知道这很令人困惑,因为“泛型”是一个有时用来谈论参数多态性的术语。
  • 是的,你绝对是对的.. 谢谢指出

标签: scala generics


【解决方案1】:

如果您遵循以下原则,它会起作用:

trait User[T] {
  def save(item:Option[T]): Option[T]
}
class UserAdmin extends User[UserA] {
  def save(item: Option[UserA]): Option[UserA] = ???
}
...

【讨论】:

    【解决方案2】:

    除了@mfirry's 之外的另一个选项是,我们使用类型成员(而不是类型参数)。

    trait User {
      type T
      def save(item:Option[T]): Option[T]
    }
    class UserAdmin extends User {
      type T = UserA
      def save(item:Option[UserA]): Option[T]
    }
    class UserSomethingElse extends User {
      type T = UserB
      def save(item:Option[UserB]): Option[T]
    }
    

    在我的实际情况下,这实际上更好,因为我有几个这样的类型,它们的具体实现在子类中会有所不同(参数和返回参数的类型不同)。所以是这样的:

    trait User {
      type T
      type R
      def save(item:Option[T]): Option[R]
    }
    class UserAdmin extends User {
      type T = UserA
      type R = UserAA
      def save(item:Option[T]): Option[R]
    }
    class UserSomethingElse extends User {
      type T = UserB
      type R = UserBB
      def save(item:Option[T]): Option[R]
    } 
    

    这篇文章很有帮助:http://www.artima.com/weblogs/viewpost.jsp?thread=270195

    【讨论】:

    • 你的回答救了我。这就是我一直在寻找的。​​span>
    【解决方案3】:

    请记住,此时T 并不表示typeclass,而是用作占位符。所以可能有一个T in shapeless 但它与占位符T 没有任何联系。

    这是对Type polymorphism的一个很好的介绍:https://twitter.github.io/scala_school/type-basics.html

    所以基本上就像@mfirry 已经建议的那样:

    trait User[T] { // T is placeholder
      def save(item:Option[T]): Option[T]
    }
    
    new User[String] {
      // using override her is considered best practice
      override def save(item:Option[String]): Option[String] = item
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    相关资源
    最近更新 更多