scala - 是否有可能实现(在 Scala 中)自动实现包装类方法的多态包装类?

标签 scala reflection polymorphism

我想实现一个类似这样的包装器类:

class Wrapper[A](wrapped: A) {
  ...
}

我希望它表现得像这样:

val a: Wrapper[Int] = new Wrapper(2)
val b: Wrapper[Int] = new Wrapper(3)

val c = a + b  // "c" should be equal to Wrapper(5)
val d = a * b  // "d" should be equal to Wrapper(6)

val e: Wrapper[String] = new Wrapper("Hello ")
val f: Wrapper[String] = new Wrapper("World")

val g = e + f // "g" should be equal to Wrapper("Hello World")

但我不想在 Wrapper 类中手动实现“+”和“*”方法;因为通常我不知道类 A 将具有哪些方法,并且我希望 Wrapper 具有 A 具有的所有方法,对于任何 A。

(在 Scala 中)这可能吗?

我怀疑答案是否定的,但我想确认一下。如果是这样,是否有其他方法可以实现这种通用行为?

最佳答案

是的,在 Scala 中是可能的,Monoid 可以帮助您实现这一点。

  1. 创建Monoid,通过某种方法帮助提升类型
  2. Monoid 对象中使用 extendMonoid trait 实现指定类型 Monoid
  3. 像下面的 IntMonoid StringMonoid 一样实现 custom 方法。

  4. 创建用于隐式MonoidOp,将type转换为MonoidOp,如下所示: WrapperMonoIdOpimplicit def wrapperMonoid

代码示例:

//It's a Monoid that lift a type to Monoid
trait Monoid[A] {
  def mappend(a1: A, a2: A): A
}
object Monoid {
  implicit object IntMonoid extends Monoid[Int] { //Implement method with type
    override def mappend(a1: Int, a2: Int): Int = a1 + a2
  }
  implicit object StringMonoid extends Monoid[String] {
    override def mappend(a1: String, a2: String): String = a1 + "" + a2
  }
}
trait WrapperMonoIdOp[A] {  //MonoidOp it will be used to implicit convert type to the MonoIdOp
  val F: Monoid[A]
  val value: A
  def +(a2: Wrapper[A]): Wrapper[A] = {
    new Wrapper[A](F.mappend(value, a2.wrapped))
  }
}
class Wrapper[A](val wrapped: A) {
  override def toString: String = wrapped.toString
}
object TmpTest {
  implicit def wrapperMonoid[A: Monoid](a: Wrapper[A]): WrapperMonoIdOp[A] = new WrapperMonoIdOp[A] { //implicit convert the wrapper class to MonoidOp
    override val F: Monoid[A] = implicitly[Monoid[A]] //implictly Monoiid
    override val value: A = a.wrapped
  }
  def main(args: Array[String]): Unit = {
    val a = new Wrapper(1)
    val b = new Wrapper(2)
    println(a + b)
    val c = new Wrapper("hello")
    val d = new Wrapper("world")
    println(c + d)
  }
}

如果我们用未实现的类型调用+,编译器会抛出编译错误,比如:

val a = new Wrapper(1.1)
val b = new Wrapper(1.2)
a + b // compiler will throw type mismatch.

教程:http://eed3si9n.com/learning-scalaz/7.0/sum+function.html

关于scala - 是否有可能实现(在 Scala 中)自动实现包装类方法的多态包装类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41542834/

相关文章:

nhibernate - 使用 NHibernate 正确映射多态关系

java - Java 中的动态方法调度

C#泛型继承

scala - val 和单例对象之间的细微差别是什么?

java - 为被测依赖类创建 stub

string - Scala:替换字符串中位置 i 处的字符

java - 是否可以使用 getter/setter 方法映射成员?

reflection - DLR 和反射

scala - 删除类型字段

Scala:如何从文件中读取文本时删除空行