scala - Scala 中的子类型 : what is "type X <: Y"?

标签 scala type-constraints subtype

任何人都可以在下面的代码中解释子类型(<:) 吗?为什么可以这样使用?当我们使用它?谢谢。

trait SwingApi {

    type ValueChanged <: Event

    val ValueChanged: {
       def unapply(x: Event): Option[TextField]
    }

    type ButtonClicked <: Event

    val ButtonClicked: {
        def unapply(x: Event): Option[Button]
    }

    type TextField <: {
        def text: String
        def subscribe(r: Reaction): Unit
        def unsubscribe(r: Reaction): Unit
    }

    type Button <: {
        def subscribe(r: Reaction): Unit
        def unsubscribe(r: Reaction): Unit
    }

}

最佳答案

我知道那个密码! :)

因此,让我们确保您了解 <:意思是,以防万一。 A <: B表示 A必须是 B 的子类型,或者,换句话说,A 的每个实例将是 B 的一个实例以及(但反之亦然)。

例如,我们知道每个 java 类都是 <: Object (例如 String <: Object )。

接下来,为什么type ValueChanged <: Event .这通常出现在蛋糕图案中,但我将跳过对此的解释(类(class)确实提到了蛋糕图案,并提供了链接 iirc)。

这意味着对于任何扩展 SwingApi , 类型 ValueChanged必须是 Event 的子类型.这样就可以调用Event使用 ValueChanged 类型声明的任何内容的方法,而事先不知道那是什么类型。

这类似于下一个用法:

type TextField <: {
    def text: String
    def subscribe(r: Reaction): Unit
    def unsubscribe(r: Reaction): Unit
}

我们在此声明 TextField应该有这些方法,所以当我们得到 TextField 类型的东西时(如ValueChanged提取器返回的),我们可以调用这些方法就可以了。我们可以这样写代码:
trait MyStuff extends SwingApi {
  def subscribeTo(event: ValueChanged) = event match {
    case ValueChanged(textField) => textField.subscribe(myReaction)
  }

  def myReaction: Reaction
}

此时,SwingApi也不是 MyStuff知道哪些类型将用于ValueChangedTextField , 然而,他们可以在普通代码中使用它们。

关于 type 经常被忽视的一个有趣事实声明是它们可以被类覆盖。也就是说,我可以这样写:
class SwingImpl extends SwingApi {
  class TextField {
    def text: String = ???
    def subscribe(r: Reaction): Unit = ???
    def unsubscribe(r: Reaction): Unit = ???
  }

  // etc
}

最后,您可能想知道这有什么用。我举一个例子。自然地,您希望生产代码在屏幕等上显示图形元素,也许您可​​以编写一个单独的类在 Web 服务器中实现它。但是,我认为类(class)利用了它,您可以编写实现它的类,而不是作为显示这些组件的东西,而是作为测试类,验证与这些组件的交互是否正确完成。

也就是说,您可以拥有 SwingImpl扩展 SwingApi并在您的桌面上显示这些内容,以及 SwingTest这也扩展了 SwingApi ,但只是让人们验证正在做什么。

关于scala - Scala 中的子类型 : what is "type X <: Y"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20508529/

相关文章:

c# - Java 继承约束

c# - 是否可以将 C# 泛型方法类型参数约束为 "assignable from"包含类的类型参数?

xml - 如何在Scala中的xml节点之间添加 'cut&paste'元素?

Typescript 对类型参数类的泛型约束

java - 多行字符串文字的正则表达式生成 `StackOverflowError`

scala - 将类限制为 Scala 中的特征和结构子类型

java - "Java subtype"和 "true subtype"有什么区别

vbscript - 是否可以创建错误并将其分配给 VBScript 中的错误子类型变量?

scala - 如何在 IntelliJ 14 中关闭 Play 路由文件的自动格式化?

scala - 类型参数不符合 trait Subtractable 的类型参数边界