Scala:如何使用类型参数化在类中打印

时间:2015-12-03 16:03:46

标签: scala types

我有一个像这样的示例代码:

trait X{
  val a=1;
  val b=2;
}

case class Y(override val a:Int, override val b:Int) extends X{
  def sum(c:Int)=a+b+c
}

case class Z(override val a:Int, override val b:Int) extends X{
  def sum(c:Int)=a+b+c+10
}



object Test{
  def main(args: Array[String]) {
    val z = Z(1, 2)
    val y = Y(3, 4)
    println (y.sum(5))
    MyTest[Z].myprint(z) //error here
  }
}

class MyTest[A] {
  def myPrint(z: A): Unit =
    if (z.isInstanceOf[A]) {
      val c = z.asInstanceOf[A]
      println(c.sum(4)) //error here
    }
}

我要做的是创建一个参数化类MyTest,其函数将打印作为参数传递的类的sum函数。我收到两个错误:

  1. 无法解析符号MyTest
  2. 我不能写c.sum(),因为很明显编译器没有关于可以在A中传递什么类的信息。
  3. 请注意,如果我将方法myPrint放在Test中,这是一个更好的设计,我还有第二个问题。

    这可以解决什么问题?

2 个答案:

答案 0 :(得分:3)

你做不到

MyTest[Z].myprint(z)

因为它是一个类,所以你必须首先实例化它

val test = new MyTest[Z]
test.myprint(z)

通知您宣布myPrint并使用myprint这是一个不同的标识符......

或者您可以使用通用方法

创建object
object MyTest {
  def myPrint[A](z: A): Unit = ???
}

关于另一个问题,如果你想调用sum告诉编译器myPrint采用具有此方法的类型的参数。例如,你可以把它放在你的特质

trait X {
  val a = 1
  val b = 2

  def sum(c: Int): Int
}

并在子类中实现它

然后您可以将其声明为

def myPrint(x: X): Unit =
  println(x.sum(4))
}

我把那里4作为参数,因为我不知道你真正想要实现的是什么,因为你的代码没有传递任何参数来声明你接受一个Int

另一种声明类型(而不是将sum添加到X特征的方法是创建另一个特征

trait Summable {
  def sum(c: Int): Int
}

让你的类实现它

case class Y(override val a:Int, override val b:Int) extends X with Summable

然后myPrint需要接受Summable而不是X

最后,您可以使用结构类型并声明myPrint,如下所示

def myPrint(x: { def sum(a: Int): Int }): Unit =
  println(x.sum(4))
}

答案 1 :(得分:1)

您可以将Structural TypesBounds一起使用,它基本上定义了给定类型应该具有哪些方法或属性,以便与您的类一起使用。它的功能与鸭子类型的动态语言非常相似。

这样你的类定义可以重写如下:

class MyTest[A <: { def sum(i: Int): Int }]

由于sum方法接收到一个参数,myPrint内的调用也应该通过它。修复一下,代码的工作版本是:

trait X {
  val a = 1;
  val b = 2;
}

case class Y(override val a: Int, override val b: Int) extends X {
  def sum(c: Int) = a + b + c
}

case class Z(override val a: Int, override val b: Int) extends X {
  def sum(c: Int) = a + b + c + 10
}

class MyTest[A <: { def sum(i: Int): Int }] {
  def myPrint(z: A): Unit =
    println(z.sum(0)) // I added a zero just to fix the example
}

object Test {
  def main(args: Array[String]) {
    val z = Z(1, 2)
    val y = Y(3, 4)
    println(y.sum(5))
    new MyTest[Z]().myPrint(z) //error here
  }
}