Scala传递方法到超级构造函数

时间:2014-05-29 19:54:16

标签: scala constructor functional-programming

我希望有一个层次结构,基类可以在其构造函数中获取一个函数,派生类可以提供一个方法作为该函数。有一种方法可以在下面做,但它很难看。我必须在super的构造函数的构造函数arg列表中声明子函数。这意味着该函数是匿名的,因此不是Child类的方法(虽然我不认为我关心它)。实际代码很长,最终难以阅读,特别是如果我有多个这样的函数。

因此:

class A[T](s1: String, s2: String, w: (String, String) => Unit){
  def go: Unit = {
    w(s1, s2)
  }
}

val externalWriter = { (s1: String, s2: String) =>
    println (s1+s2)
}

val w1 = new A[String]("Hello ", "world", externalWriter)
w1.go

case class B(s1: String, s2: String) extends A[String](s1, s2, w = { (a: String, b: String) =>
    println ("Class B:"+a+b)
  }){
  def write: Unit = go
}

val w2 = B("Hey  ","guys")
w2.write

w1.go打印“Hello world”,w2.write打印“B级:嘿伙计们”。所以这就是我想要的,但有没有办法让w成为B类的方法或val,并仍然将它传递给super的构造函数?

2 个答案:

答案 0 :(得分:2)

你可以做这样的事情,让你作为抽象成员传递的函数,然后在你的case类中实现它,并提供一个预先实现的实现,通过构造函数接受它:

  abstract class A(s1: String, s2: String) {
    def w: (String, String) => Unit
    def go(): Unit = {
      w(s1, s2)
    }
  }

  class InlineA(s1: String, s2: String, w1: (String, String) => Unit) extends A(s1, s2) {
    def w = w1
  }

  val externalWriter = { (s1: String, s2: String) =>
    println(s1 + s2)
  }

  val w1 = new InlineA("Hello ", "world", externalWriter)
  w1.go()

  case class B(s1: String, s2: String) extends A(s1, s2) {
    def w = { (a: String, b: String) =>
      println("Class B:" + a + b)
    }
    def write(): Unit = go()
  }

  val w2 = B("Hey  ", "guys")
  w2.go()

答案 1 :(得分:2)

我会做一些类似于monkjack的解决方案,但使用更多的mixin模式。这里的关键区别在于我使用A的匿名优化来创建w1,允许我将w作为方法。

abstract class A(s1: String, s2: String) {
  def w(arg1: String, arg2: String): Unit
  def go(): Unit = {
    w(s1, s2)
  }
}

val w1 = new A("Hello", "World") {
  def w(a: String, b: String): Unit = println(a + b)
}
w1.go()

case class B(s1: String, s2: String) extends A(s1, s2) {
  def w(a: String, b: String): Unit = println("Class B:" + a + b)
  def write: Unit = go
}

val w2 = B("Hey  ", "guys")
w2.write

trait C {
  def w(a: String, b: String): Unit = println("Trait C:" + a + b)
}

val w3 = new A("Bye ", "everyone") with C
w3.go()