【问题标题】:Scala passing method to supers constructorScala将方法传递给超级构造函数
【发布时间】:2014-05-29 19:54:16
【问题描述】:

我希望有一个层次结构,其中基类可以在其构造函数中使用一个函数,而派生类可以提供一个方法作为该函数。下面有一种方法可以做到这一点,但它很难看。我必须在超级构造函数的构造函数 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,并且仍然将它传递给超级的构造函数?

【问题讨论】:

    标签: scala constructor functional-programming


    【解决方案1】:

    我会做一些类似于 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()
    

    【讨论】:

    • 我不知道你可以在一个新的、非常有趣的主体中定义 w。缺点是你必须知道才能使用它。 @monkjack 会使选项明确。如果它有一个很长的wdefinition,这也会相当冗长,因为它会在使用它的范围内内联。嗯...
    • 聪明但在很多情况下都很有用。
    • 您也可以在另一个特征中定义w,如果您不想内联,则在实例化时混合该特征。我再补充一个例子
    • 好的,现在你有了。我一直在努力解决如何使用特征来做到这一点。现在,您只需在实例化时使用简单的with N 为任意编写器和 mixin 定义一个新特征。你教会了我一些非常有用的东西,我希望其他人会觉得这很有帮助。
    【解决方案2】:

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

      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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-03
      • 2019-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      相关资源
      最近更新 更多