[英]How to define a type for a generic type
假设我有以下代码:
trait Trait[T <: Trait[T]] {
def merge(t: T): T
}
case class A[T <: Trait[T]](t: T, i: Int)
case class B[T <: Trait[T]](t: T, str: String)
有没有一种方法可以定义一种类型来缩写我对 A 类和 B 类的定义?
所以像:
type T2 = _ <: Trait[T2] // ???
case class A[T2](t: T2, i: Int)
case class B[T2](t: T2, str: String)
实际上,您不需要类型的别名,而是需要绑定的别名。
简而言之,您应该在需要的地方保留 F 边界。 实际上,这不是代码重复。 Trait
, A
, B
类型参数T
实际上是三个不同的类型参数,它们可以有不同的界限。
但理论上您可以使用 宏注释来缩写边界,尽管这样做并不值得,而且通常会很危险,因为这可能会让您的队友感到惊讶,会使调试变得更加复杂,并且会使您的 IDE 感到困惑
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
@compileTimeOnly("enable macro annotations")
class fbound extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro FBoundMacro.impl
}
object FBoundMacro {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
def addFBound(tparam: Tree): Tree = tparam match {
case q"$mods type $name[..$tparams] >: $low <: $high" =>
val tparamsNames = tparams.map {
case q"$_ type $nme[..$_] >: $_ <: $_" => nme
}
val fBound = tq"Trait[$name[..$tparamsNames]]"
val high1 = high match {
case tq"$EmptyTree" => fBound
case tq"..$withTypes { ..$refinements }" =>
val withTypes1 = withTypes :+ fBound
tq"..$withTypes1 { ..$refinements }"
case tq"$typ" => tq"$typ with $fBound"
}
q"$mods type $name[..$tparams] >: $low <: $high1"
}
annottees match {
case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" :: tail =>
val tparams1 = addFBound(tparams.head) :: tparams.tail
q"""
$mods class $tpname[..$tparams1] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }
..$tail
"""
}
}
}
用法:
trait Trait[T <: Trait[T]] {
def merge(t: T): T
}
@fbound case class A[T](t: T, i: Int)
@fbound case class B[T](t: T, str: String)
//scalac: {
// case class A[T <: Trait[T]] extends scala.Product with scala.Serializable {
// <caseaccessor> <paramaccessor> val t: T = _;
// <caseaccessor> <paramaccessor> val i: Int = _;
// def <init>(t: T, i: Int) = {
// super.<init>();
// ()
// }
// };
// ()
//}
//scalac: {
// case class B[T <: Trait[T]] extends scala.Product with scala.Serializable {
// <caseaccessor> <paramaccessor> val t: T = _;
// <caseaccessor> <paramaccessor> val str: String = _;
// def <init>(t: T, str: String) = {
// super.<init>();
// ()
// }
// };
// ()
//}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.