【问题标题】:Polymorphism in DafnyDafny 中的多态性
【发布时间】:2023-03-23 04:27:02
【问题描述】:

我正在尝试在 Dafny 中进行多态性,但我无法使其工作。我没有找到任何文档来帮助我解决这个问题。这是代码:https://rise4fun.com/Dafny/uQ1w

trait Atom {
  var Leaf? : bool;
}

class Leaf extends Atom {
  constructor() {
    this.Leaf? := true;
  }
}

class Node extends Atom {
  var left : Atom;

  constructor() {
    this.Leaf? := false;
    this.left := new Leaf();
  }
}

method Main() {
  var root := new Node();
  root.left := new Node();

  root.left.left := new Node();
}

错误:

Dafny 2.1.1.10209
stdin.dfy(24,12): Error: member left does not exist in trait Atom
1 resolution/type errors detected in stdin.dfy

【问题讨论】:

    标签: polymorphism dafny


    【解决方案1】:

    表达式root.left 的类型为Atom(因为这是Node 类中left 字段的类型)。因此,类型系统不知道root.left指向的对象是Leaf还是Node,尤其不能保证这个对象有left属性。

    您可以通过先将左孩子分配给变量,然后访问其next 属性来规避此问题:

    method Main() {
      var root := new Node();
    
      // root_l is inferred to have type 'Node' instead of 'Atom'  
      var root_l := new Node();
      root.left := root_l;
    
      // Here root_l has type Node, so it has a 'left' attribute.
      root_l.left := new Node();
    }
    

    在面向对象的语言(例如 Java)中,这也可以通过向下转换来解决(例如 ((Node)root.left).left := new Node();,但我不知道 Dafny 是否支持这种转换。

    【讨论】:

    • 您的示例有效,但没有说明我应该如何做一些事情。在同一示例中检查 displayTree rise4fun.com/Dafny/iV0U
    • 在层次结构的顶部 (Atom) 实现一个方法来区分 this 是一个子 (Leaf) 还是另一个 (Node) 的实例不是任何 OO 语言的推荐实践。您可以在 Atom 中声明 display() 抽象(即没有实现)并在每个子类中使用其特定实现覆盖它。有关示例,请参见 rise4fun.com/Dafny/6wslZp
    【解决方案2】:

    对于这个特定的例子,使用datatype 是有意义的:

    datatype Atom = Leaf | Node(left: Atom)
    
    method Main() {
      var root := Atom.Node(Atom.Node(Atom.Leaf));
    }
    

    编译器为Atom 两种类型提供谓词atom.Leaf?atom.Node?。例如,root.Node?true

    【讨论】:

    • 我已经在使用datatype,我想重构我的代码。
    • 如果我想要很多特定于 Node 和 Atom 的函数,你建议如何构建代码?就像这个例子中的displayTreerise4fun.com/Dafny/iV0U
    • @AndriciCezar 使用match。这真好;您的代码最终要短得多,它只是说明了您的意思。这是一个示例:rise4fun.com/Dafny/jFtz
    • datatype 并不是对所有事情都有好处,但是当可能的子类集很小且“封闭”(不太可能经常更改)时,它确实会发光。在 Dafny 中这并不是一个全新的想法。 ML、Haskell 和 Rust 等语言具有相同的东西,但有几个不同的名称。
    猜你喜欢
    • 2021-07-03
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 2016-03-19
    • 2020-07-04
    • 1970-01-01
    • 2011-05-12
    相关资源
    最近更新 更多