如何将方法限制为仅用于特定类型?

d-_*_*_-b 4 scala

假设我下面有一个案例类

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]()应导致编译错误。

ElB*_*ulP 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]]()
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。我很想知道是否还有更好的方法。


zig*_*tar 5

您可以B通过使用隐式参数来强制类型参数等于某种类型:

def foo[A](implicit e: A =:= B): …
Run Code Online (Sandbox Code Playgroud)

也看到这个问题

为该答案增加更多价值。以下代码显示了如何使用隐式参数e: A =:= String将转换AString

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)

解答OP存在的问题

这个问题要简单得多:仅使方法的参数化参数ASomeCaseClass[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)