简体   繁体   English

Scala-使用泛型方法定义特征

[英]Scala - define a trait with generic methods

How do I define a trait with generic arguments in its methods and then override with the specific typed arguments? 如何定义在其方法中具有通用参数的特征,然后使用特定的类型化参数覆盖?

An example: 一个例子:

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]
}

With this, I get the error not found: type T even though it is defined in shapeless 这样,我得到的错误not found: type T即使not found: type T是在无形中定义的,也要not found: type T

It works if you something along these lines: 如果您遵循以下原则,它将起作用:

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

One has to keep in mind that T at this moment does not denote a type or class but is used as a placeholder. 必须记住,此时T并不表示typeclass而是用作占位符。 So it may be that there is a T in shapeless but it has no connection to the placeholder T . 因此,可能存在无定形的T ,但它与占位符T没有任何关系。

Here is a nice introduction to Type polymorphism : https://twitter.github.io/scala_school/type-basics.html . 这是有关Type polymorphism的很好的介绍: https : //twitter.github.io/scala_school/type-basics.html

So basically as @mfirry already suggested: 因此基本上就像@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
}

Another option, besides @mfirry's is this, where we use a type member instead (versus a type parameter). 除了@mfirry以外,另一个选择是,我们使用类型成员(而不是类型参数)。

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]
}

In my real case this is actually better since I have several such types whose concrete implementations will vary in the subclasses (different types for the arguments and the return parameters). 在我的真实情况下,这实际上更好,因为我有几种这样的类型,它们的具体实现在子类中会有所不同(参数和返回参数的不同类型)。 So something like this: 所以像这样:

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]
} 

This article was helpful: http://www.artima.com/weblogs/viewpost.jsp?thread=270195 本文很有帮助: http : //www.artima.com/weblogs/viewpost.jsp? thread= 270195

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM