Chapel 中是否有与 Fortran 的 select 类型语句等效的语句?
Is there an equivalent to Fortran's select type statement in 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 的 "select type" 语句的 Fortran 2008 代码。做
Chapel 提供了类似的声明,或者这个示例是否必须以完全不同的方式编码才能在 Chapel 中工作?我在 Chapel 文档中找不到任何相关内容。
理解您的代码为何不起作用的关键是 Chapel 中的 myVar.type
指的是变量的 static 类型而不是其 dynamic 类型。因此,即使您和我都可以看到 anim
最初是 Fish
,后来是 Bird
,anim.type
将始终是 Animal
,因为它被声明为 var anim: Animal;
赋予它静态类型 Animal
。您可以通过将 main() 函数更改为以下 (try it online):
来查看这一点
proc main() {
use SomeAnimals;
var anim: Animal;
anim = new Fish();
writeln(anim.type:string);
anim = new Bird();
writeln(anim.type:string);
} // proc main
输出将是:
Animal
Animal
在 Chapel 中推断 class 变量的动态类型的一种方法是对其应用强制转换运算符 (:
),其行为类似于 C++ 中的动态强制转换。即,如果我尝试将静态类型为 Animal
的变量转换为 Fish
但它实际上是 Bird
,我将返回 nil
,表明 class 对象既不是 Fish
也不是 Fish
.
的子 class
因此,重写您的 main() 的行为将如下所示 (try it online):
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
(我使用 shorthand if classVar ...
表示 if classVar != nil ...
)
回到你关于 Chapel 是否有类似 Fortran 类型的 select 语句的具体问题,目前没有。对于静态类型的推理(如 int
vs. real
vs. my record R
vs. a subclass of C
),像你一样在变量类型上使用 select 语句是完全合理的(或者你可以提供一个函数的重载,我们会根据参数的静态类型选择正确的函数)。但是对于你在 class 层次结构中工作并且必须推断对象的动态类型的情况,你的主要工具将是强制转换,如上所述,或动态调度,或在 class区分大小写(可以认为是动态转换的手动实现)。
我想在 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 的 "select type" 语句的 Fortran 2008 代码。做 Chapel 提供了类似的声明,或者这个示例是否必须以完全不同的方式编码才能在 Chapel 中工作?我在 Chapel 文档中找不到任何相关内容。
理解您的代码为何不起作用的关键是 Chapel 中的 myVar.type
指的是变量的 static 类型而不是其 dynamic 类型。因此,即使您和我都可以看到 anim
最初是 Fish
,后来是 Bird
,anim.type
将始终是 Animal
,因为它被声明为 var anim: Animal;
赋予它静态类型 Animal
。您可以通过将 main() 函数更改为以下 (try it online):
proc main() {
use SomeAnimals;
var anim: Animal;
anim = new Fish();
writeln(anim.type:string);
anim = new Bird();
writeln(anim.type:string);
} // proc main
输出将是:
Animal
Animal
在 Chapel 中推断 class 变量的动态类型的一种方法是对其应用强制转换运算符 (:
),其行为类似于 C++ 中的动态强制转换。即,如果我尝试将静态类型为 Animal
的变量转换为 Fish
但它实际上是 Bird
,我将返回 nil
,表明 class 对象既不是 Fish
也不是 Fish
.
因此,重写您的 main() 的行为将如下所示 (try it online):
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
(我使用 shorthand if classVar ...
表示 if classVar != nil ...
)
回到你关于 Chapel 是否有类似 Fortran 类型的 select 语句的具体问题,目前没有。对于静态类型的推理(如 int
vs. real
vs. my record R
vs. a subclass of C
),像你一样在变量类型上使用 select 语句是完全合理的(或者你可以提供一个函数的重载,我们会根据参数的静态类型选择正确的函数)。但是对于你在 class 层次结构中工作并且必须推断对象的动态类型的情况,你的主要工具将是强制转换,如上所述,或动态调度,或在 class区分大小写(可以认为是动态转换的手动实现)。