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)
有关 add
和 reverse
方法的示例,请参阅此问题的其他答案。
您可以为此使用证据参数:
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
如果你想要 Int
和 String
的特定构造函数并且无法获得足够的隐含证据,你可以这样做:
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>
我想用特定类型重载抽象 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)
有关 add
和 reverse
方法的示例,请参阅此问题的其他答案。
您可以为此使用证据参数:
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
如果你想要 Int
和 String
的特定构造函数并且无法获得足够的隐含证据,你可以这样做:
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>