trait Base
trait Plugin { base: Base =>
def asBase: Base & Plugin = this
}
class Mix extends Base, Plugin
val plug: Plugin = new Mix
val baseA: Base= plug.asBase
val baseB: Base = plug // snorts with "Found: Plugin. Required: Base
Run Code Online (Sandbox Code Playgroud)
为什么?如果我是正确的,则遵守里氏替换原则,因为 的所有实例Plugin都是具体类型,该类型是包含 的子类型的混合Base。因此,Base可以用type的对象替换type的对象Plugin,而不影响程序的正确性。
里氏原理说
\nhttps://en.wikipedia.org/wiki/Liskov_substitution_principle
\n\n\n子类型要求:设是关于类型 的
\n\xcf\x95(x)对象的可证明属性。对于类型为 的子类型的对象,则应该如此。xT\xcf\x95(y)ySST子类型中的先决条件无法得到强化。
\n子类型中的后置条件不能被削弱。
\n不变量必须保留在子类型中。
\n
里氏原则是关于子类型的。里氏原理现在不适用,因为Plugin它不是Base
implicitly[Plugin <:< Base] // doesn\'t compile\nRun Code Online (Sandbox Code Playgroud)\n(比/sf/answers/5303386441/<:<弱,但这对我们来说没问题;如果是ie的子类型,那么更会是)。<: PluginBasePlugin <: Baseimplicitly[Plugin <:< Base]
trait Plugin { base: Base => }我猜您将trait Plugin extends Base子类(继承)与子类型混淆了
https://typelevel.org/blog/2017/02/13/more-types-than-classes.html
\n\n\ntrait Plugin extends Base意味着它Plugin是 的子类Base。特别是,这意味着Plugin是 的子类型Base,因此 的所有子类型Plugin都是 的子类型Base。\n但是trait Plugin { base: Base => }意味着 的所有子类Plugin都必须是 的子类Base。这并不意味着 的所有子类型都必须Plugin是 的子类型Base(而且,这并不意味着Plugin是 的子类型Base)。事实上,声明类型很容易
type SubPlugin <: Plugin\nRun Code Online (Sandbox Code Playgroud)\n这不是 的子类型Base
implicitly[SubPlugin <:< Base] // doesn\'t compile\nRun Code Online (Sandbox Code Playgroud)\n\n\n的所有实例
\nPlugin都是具体类型,该类型是包含 的子类型的混合Base。
即使 的所有值(OOP 实例)Plugin都是 this 的值(实例),Base这并不构成Plugin的子类型Base,并且这并不意味着类型的所有术语Plugin都是类型 的术语Base。例如,术语xinval x: Plugin = ???不是类型 的术语Base。
您不应该将类型(仅)视为该类型的所有值的集合(特别是这在类型级编程中变得很重要,其中值根本不那么有趣)。\n集合可以是一个模型(在逻辑中)意义: https: //en.wikipedia.org/wiki/Model_theory)用于类型。但集合和类型不同
\n\nhttps://math.stackexchange.com/questions/489369/difference- Between-a-type-and-a-set
\nhttps://planetmath.org/11typetheoryversussettheory
\n例如,如果我们定义两个抽象类型
\ntype A\n\ntype B\nRun Code Online (Sandbox Code Playgroud)\n那么就没有这些类型的值。因此,这些集合在集合论意义上是相等的(空集)。但这些类型是不同的。在同伦类型理论(HoTT,https://en.wikipedia.org/wiki/Homotopy_type_theory)中1 = 2, 和1 = 3是两种没有任何值的类型,但却是两种不同的类型。
\n\n因此,
\nBase可以用type的对象替换type的对象Plugin,而不影响程序的正确性。
总有一些程序在运行时不会失败,但在编译时会被拒绝。例如,if true then 1 else "a"运行时不会失败,但可以被没有子类型的语言拒绝,例如 Haskell(但不会被 Scala 拒绝,它认为这是Any)。Scala 会拒绝,val x: Int = if (true) 1 else "a"尽管这在运行时也不会失败。足够丰富的类型系统不可能同时健全和完整。通常,健全性优于完整性
您可能会问为什么不总是trait Plugin { base: Base => }与 含义相同trait Plugin extends Base。嗯,这是 Scala 类型系统创建者的设计决定。特别是,如果这是相同的,那么两个不同的特征trait A {this: B =>}将trait B {this: A =>}具有相同的类型。
同样在 中trait Plugin extends Base,Base必须是一个类/特征。但在 中trait Plugin { base: Base => },Base可以是一种类型。
更重要的是 Scala 惯用语:特质 TraitA 扩展 TraitB 或特质 TraitA { self: TraitB => }
\n| 归档时间: |
|
| 查看次数: |
76 次 |
| 最近记录: |