2

我是 Scala 的新手。我有一个Class A那个。我也有那个也有extendsClass CClass BextendsClass C

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

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

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

4

1 回答 1

2

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

trait Function1[-T1, +R] extends AnyRef

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

然而,我们可以做的是创建一个类型类,然后包含一个实现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其成员是A,BA => B,但是你解决了子类型化问题。

于 2018-01-15T14:02:37.673 回答