如何在Scala

时间:2018-01-15 13:27:56

标签: scala function inheritance functional-programming extending-classes

我是Scala的新手。 我有一个Class A extends一个Class C。我还有一个Class Bextends一个Class C

我希望类型A->B的函数对象也可以扩展C(以及其他派生类型,例如A->(A->B))。但我在下面的“scala编程”中读到:

  

函数文字被编译成一个在运行时实例化的类   是一个函数值。

是否有某种方法可以自动让A->B extend C,然后手动创建一个代表该功能的新类?

1 个答案:

答案 0 :(得分:2)

Scala中的函数通过FunctionN特征建模。例如,简单的单输入一输出函数都是以下特征的实例:

trait Function1[-T1, +R] extends AnyRef

所以你问的是“如何让Function的实例也成为C的子类”。这不是通过标准子类型/继承来实现的,因为很明显我们无法修改Function1特征来扩展您的自定义类C。当然,我们可以按照你的建议组成一个新的类来表示函数,但是这只会带我们到目前为止并且实现起来并不容易,更不用说你想用作C的任何函数了必须首先转换为你的伪功能特征,这会让事情变得可怕。

然而,我们可以做的是创建一个类型类,然后包含A -> B的实现。

我们以下面的代码为例:

trait A
trait B
trait C[T]

object C {
  implicit val fa = new C[A] {}
  implicit val fb = new C[B] {}
  implicit val fab = new C[Function1[A, B]] {}
}


object Test extends scala.App {

  val f: A => B = (a: A) => new B {}

  def someMethod[Something: C](s: Something) = {
    // uses "s", for example:
    println(s)
  }

  someMethod(f) // Test$$$Lambda$6/1744347043@dfd3711

}

您尚未指定制作A - >的动机B扩展C,但显然你希望能够放入A,B和A - > B在“同一个保护伞”下,因为你有一些方法(称为someMethod),它采用C所以继承你可以传递类型A,B或A的值 - > B.

使用类型类,您可以实现相同的功能,并具有一些额外的优势,例如有一天将D添加到系列中而不更改现有代码(您只需在范围内的某处实现类型为C[D]的隐式值)。

所以,不要让someMethod接受C的实例,而只需要某种类型的东西(让我们称之为s)(让我们称之为Something), C[Something]必须存在的约束。如果你传递了一个不存在C实例的东西,你将收到一个错误:

trait NotC
someMethod(new NotC {}) 
// Error: could not find implicit value for evidence parameter of type C[NotC]

你实现同样的目标 - 你有一个C家庭,其成员是ABA => B,但你可以解决问题。