假设我下面有一个案例类
case class SomeCaseClass[M] private (
value: String
)
在另一个文件中,我具有以下特征和对象。
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]]()
}
我应该如何修改代码,以便将init方法限制为只能与SomeCaseClass [_]类型一起使用,而不能与上述任何类型的字符串一起使用?
理想情况下,对代码进行了一些修改,第val aaa: SomeTrait[String] = init[String]()
行应导致编译错误。
答案 0 :(得分:6)
这是我想出的:
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]]()
失败并
ScalaFiddle.scala:16:错误:类型参数[String]不符合方法初始化的类型参数范围[A <:ScalaFiddle.this.SomeCaseClass [_ $ 1] forSome {type _ $ 1}]
您可以选中此scalafiddle。
我不知道这是否是最好的方法,但是init[A <: SomeCaseClass[_]]
正在添加绑定到A
的类型,并强制A
成为子类SomeCaseClass
中的。我很想知道是否还有更好的方法。
答案 1 :(得分:5)
您可以使用隐式参数强制类型参数等于某个类型B
:
def foo[A](implicit e: A =:= B): …
另请参阅this question。
为该答案添加更多价值。
以下代码显示了如何使用隐式参数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.
这个问题要简单得多:仅将方法参数设为A
的参数SomeCaseClass[A]
,而不要使用整个类型SomeCaseClass[A]
作为类型参数:
private[this] def init[A](): SomeTrait[SomeCaseClass[A]] = new
SomeTrait[SomeCaseClass[A]] {
def get(oldId: String): SomeCaseClass[A] = ???
}
答案 2 :(得分:3)
这是基于上面的答案:
case class SomeCaseClass[M] private (
value: String
)
trait SomeTrait[A] {
def get(oldId: String): SomeCaseClass[A]
}
private[this] def init[A](): SomeTrait[A] = new SomeTrait[A] {
def get(oldId: String): SomeCaseClass[A] = ???
}
val aaa: SomeTrait[String] = init[String]()
(https://scalafiddle.io/sf/KuXZc0h/3)
这不允许将SomeCaseClass
以外的其他类型与SomeTrait
一起使用。