Scala 中的泛型类型

Generic types in Scala

我想用特定类型重载抽象 class 的构造函数。例如,我有:

abstract class Polinom(v: T)

所以,当我创建 Polinom[String] 时,我想调用 constructor(String),对于 Int,我想调用 constructor(Int)。如果 T != String and T != Int 那么我调用 constructor(T)。此外,对于 T == Int 我的对象必须有方法 add,对于 T == String - reverse,对于 T != String and T != Int 对象没有这个方法。我该怎么做?

最好将其建模为 ADT,例如:

sealed trait Polinom[T] {
  def v: T
}

object Polinom {
  final case class IntPolinom private[Polinom] (v: Int) extends Polinom[Int] {
    def add(x: Int): IntPolinom =
      this.copy(v = this.v + x)
  }

  final case class StrPolinom private[Polinom] (v: String) extends Polinom[String] {
    def reverse: StrPolinom =
      this.copy(v = this.v.reverse)
  }

  final case class GenericPolinom[T] private[Polinom] (v: T) extends Polinom[T]

  def apply[T](v: Int): IntPolinom =
    IntPolinom(v)

  def apply[T](v: String): StrPolinom =
    StrPolinom(v)

  def apply[T](v: T): GenericPolinom[T] =
    GenericPolinom(v)
}
abstract class Polinom[T](v: T)

object Polinom {
  def apply(i: Int): Polinom[Int] = constructor(i)
  def apply(s: String): Polinom[String] = constructor(s)
  def apply[T](v: T): Polinom[T] = constructor(v)
}

Polinom(0)
Polinom("hello")
Polinom(None)

有关 addreverse 方法的示例,请参阅此问题的其他答案。

您可以为此使用证据参数:

class Polinom[T](v: T) {

  def add(i: Int)(implicit ev: T <:< Int) = v + i
  def reverse(implicit ev: T <:< String): String = ev(v).reverse

}

val x = new Polinom(50)
val y = new Polinom("hello")
val z = new Polinom(None)

println(x.add(3))
println(y.reverse)
//println(z.add(3)) <- Isn't allowed. Error: Cannot prove that None.type <:< Int

如果你想要 IntString 的特定构造函数并且无法获得足够的隐含证据,你可以这样做:

def this(i: Int)(implicit ev: Int =:= T) = this({
    //do special int stuff here
    println("I am in the special int constructor")
    ev(i)
  })

  def this(s: String)(implicit ev: String =:= T) = this({
    //do special string stuff here
    println("I am in the special string constructor")
    ev(s)
  })

编辑:显然,上面的内容对 OP 不起作用,尽管它似乎对我有用,但你总是可以创建一个伴随对象并重载 apply 方法,正如其他答案所建议的那样。

class Polinom[T] private(v: T)
object Polinom {
  def apply(i: Int): Polinom[Int] = new Polinom(i)
  def apply(s: String): Polinom[String] = new Polinom(s)
  def apply[T](x: T): Polinom[T] = new Polinom(x)
}

val x = Polinom(50)
val y = Polinom("hello")
val z = Polinom(None)

println(x.add(3))
println(y.reverse)
//println(z.add(3)) <- Isn't allowed. Error: Cannot prove that None.type <:< Int

Link to Scastie(演示如下)

<script src="https://scastie.scala-lang.org/j8fWjvVFS3CumCo3WbUgqQ.js"></script>