假设我下面有一个案例类
case class SomeCaseClass[M] private (
value: String
)
Run Code Online (Sandbox Code Playgroud)
在另一个文件中,我具有以下特征和对象。
trait SomeTrait[A] {
def get(oldId: String): A
:
}
object SomeObject {
private[this] def init[A](): SomeTrait[A] = new SomeTrait[A] {
def get(oldId: String): A = id(oldId)
:
}
val aaa: SomeTrait[String] = init[String]()
val bbb: SomeTrait[SomeCaseClass[String]] = init[SomeCaseClass[String]]()
}
Run Code Online (Sandbox Code Playgroud)
我应该如何修改代码,以便将init方法限制为只能与SomeCaseClass [_]类型一起使用,而不能与上述任何类型的字符串一起使用?
理想情况下,对代码进行一些修改,该行val aaa: SomeTrait[String] = init[String]()应导致编译错误。
这是我想出的:
case class SomeCaseClass[M] private (
value: String
)
trait SomeTrait[A] {
def get(oldId: String): A
}
private[this] def init[A <: SomeCaseClass[_]](): SomeTrait[A] = new SomeTrait[A] {
def get(oldId: String): A = ???
}
val aaa: SomeTrait[String] = init[String]() // Will fail
val bbb: SomeTrait[SomeCaseClass[String]] = init[SomeCaseClass[String]]()
Run Code Online (Sandbox Code Playgroud)
它失败了
ScalaFiddle.scala:16:错误:类型参数[String]不符合方法初始化的类型参数范围[A <:ScalaFiddle.this.SomeCaseClass [_ $ 1] forSome {type _ $ 1}]
您可以检查此scalafiddle。
我不知道这是否是最好的方法,但init[A <: SomeCaseClass[_]]正在添加绑定到的类型A,并强制A成为的子类SomeCaseClass。我很想知道是否还有更好的方法。
您可以B通过使用隐式参数来强制类型参数等于某种类型:
def foo[A](implicit e: A =:= B): …
Run Code Online (Sandbox Code Playgroud)
也看到这个问题。
为该答案增加更多价值。以下代码显示了如何使用隐式参数e: A =:= String将转换A为String。
def bar(b: String): Unit = println(b)
def foo[A](a: A)(implicit e: A =:= String): Unit = {
bar(e(a))
}
foo("hi") //compiles
foo(5) //error: Cannot prove that scala.this.Int =:= String.
Run Code Online (Sandbox Code Playgroud)
这个问题要简单得多:仅使方法的参数化参数A为SomeCaseClass[A],而不是将整个类型SomeCaseClass[A]用作类型参数:
private[this] def init[A](): SomeTrait[SomeCaseClass[A]] = new
SomeTrait[SomeCaseClass[A]] {
def get(oldId: String): SomeCaseClass[A] = ???
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |