教堂中是否有等同于Fortran的select type语句?

时间:2018-08-02 20:30:36

标签: oop chapel

我想尝试一下Chapel中的类和多态性,所以我试图 得到以下示例代码以工作:

module SomeAnimals {

  class Animal {
  }

  class Bird: Animal {
  }

  class Fish: Animal {
  }

  proc Bird.fly() {
    writeln("Flying ...!");
  }

  proc Fish.swim() {
    writeln("Swimming ...!");
  }

} // module SomeAnimals


proc main() {

  use SomeAnimals;

  var anim: Animal;

  anim = new Fish();

  select (anim.type) {
  when Fish do anim.swim();
  }  
  delete anim;

  anim = new Bird();

  select (anim.type) {
  when Bird do anim.fly();
  }
  delete anim;

} // proc main

这可以编译,但是在运行时,它只是退出而没有产生任何 打印。显然,由于某些原因,未执行对select语句中包含的anim.swim()和anim.fly()方法的调用。如果不使用这些select语句检查多态变量“ anim”的实际类型,则代码当然不会编译。

上面的示例实际上是对作品的直译 利用Fortran的“选择类型”语句的Fortran 2008代码。是否 Chapel提供了类似的陈述,还是必须以完全不同的方式编码此示例才能在Chapel中工作?我在教堂文档中找不到任何相关内容。

1 个答案:

答案 0 :(得分:5)

理解代码为什么不起作用的关键是Chapel中的myVar.type是指变量的 static 类型,而不是其 dynamic 类型。因此,即使您和我看到anim最初是Fish,之后是Bird,但anim.type始终是Animal,因为它被声明为{ {1}}为其指定静态类型var anim: Animal;。您可以通过将main()函数更改为以下(try it online)来看到此内容:

Animal

输出将是:

proc main() {
  use SomeAnimals;

  var anim: Animal;

  anim = new Fish();
  writeln(anim.type:string);

  anim = new Bird();
  writeln(anim.type:string);
} // proc main

在Chapel中推断类变量的动态类型的一种方法是对其应用强制转换运算符(Animal Animal ),其行为类似于C ++中的动态强制转换。也就是说,如果我尝试将静态类型为:的变量强制转换为Animal,但实际上是一个Fish,我将得到Bird的返回,表明该类对象既不是nil也不是Fish的子类。

因此,对您的main()进行重写,使其表现为您想要的(try it online):

Fish

(我使用的是proc main() { use SomeAnimals; var anim: Animal = new Fish(); var aFish = anim:Fish; if aFish then aFish.swim(); delete anim; anim = new Bird(); var aBird = anim:Bird; if aBird then aBird.fly(); delete anim; } // proc main 的简写if classVar ...

回到您的具体问题,关于Chapel是否具有类似于Fortran的类型select语句,但目前没有。为了对静态类型进行推理(例如if classVar != nil ...intrealmy record R),像您一样对变量类型使用select语句是完全合理的(或者您可以提供函数的重载,我们将根据参数的静态类型选择正确的函数)。但是,对于在类层次结构中工作并且必须推理对象的动态类型的情况,您的主要工具将是如上所述的强制转换或动态调度,或者在类中存储显式字段以区分对象之间的动态类型。案例(可以将其视为动态投射的手动实现)。