前節でZenのインタフェースについて学びました。Zenのインタフェースは静的、すなわちコンパイル時にポリモーフィズムを実現する手段です。そのため、次のコードのように実行時に異なる構造体を、1つのインタフェース変数に再代入するコードはコンパイルエラーになります。
test "vtable" {
var a = SensorA{};
var b = SensorB{};
var sensor: Sensor = a;
sensor = b;
}
error[E02046]: expected 'SensorA', found 'SensorB'
sensor = b;
~
上のコードでsensor
の型はSensor
と指定しました。しかしコンパイラは、sensor
の型がSensorA
であり、SensorB
型の値を代入しようとしている、というエラーを出力しています。
次のテストコードにある2つのok
は、共にパスします。ここからわかることは、sensor_a
とsensor_b
とは両方ともSensor
型として定義しているにも関わらず、実際の型は、それぞれSensorA
型とSensorB
型になっていることです。これはコンパイラによる型解決の結果です。
examples/ch06-polymorphism/src/vtable.zen:4:12
test "interface type" {
var a = SensorA{};
var sensor_a: Sensor = a;
ok(@TypeOf(sensor_a) == SensorA);
var b = SensorB{};
var sensor_b: Sensor = b;
ok(@TypeOf(sensor_b) == SensorB);
}
SensorA
型とSensorB
型を同じ変数で扱うための方法がvtableです。
vtableの動作確認に使用するSensor
インタフェースと、SensorA
およびSensorB
構造体を以下に示します。
examples/ch06-polymorphism/src/vtable.zen:14:34
const Sensor = interface {
fn data() u32;
};
const SensorA = struct {
latest_data: u32 = 42,
fn data(self: *SensorA) u32 {
return self.latest_data;
}
};
const SensorB = struct {
latest_data: u32 = 52,
fn data(self: *SensorB) u32 {
return self.latest_data;
}
};
fn data(sensor: Sensor) u32 {
return sensor.data();
}
vtableは、必ずポインタ型で使用します。*vtable
で始まりインタフェース型名が続きます。右辺には構造体インスタンスの参照を取ります。
var a = SensorA {};
var sensor: *vtable Sensor = &a;
vtableは実行時に値を書き換えることができます。次のコードでは、SensorA
とSensorB
のインスタンスを作成し、vtableの変数sensor
を書き換えながら、インタフェースを利用しています。
examples/ch06-polymorphism/src/vtable.zen:36:47
test "vtable" {
var a = SensorA{};
var b = SensorB{};
var sensor: *mut vtable Sensor = &a;
ok(sensor.data() == 42);
ok(data(sensor) == 42);
sensor = &b;
ok(sensor.data() == 52);
ok(data(sensor) == 52);
}
sensor.data()
の形式でインタフェースのメンバを利用することもできますし、data(sensor)
のようにSensor
型を要求する関数への引数として利用することもできます。
異なる構造体型のインスタンスを*vtable
型要素を持つ配列で一元的に扱うことができます。
examples/ch06-polymorphism/src/vtable.zen:49:56
test "array of vtable" {
var a = SensorA{};
var b = SensorB{};
const sensors = [_]*mut vtable Sensor{ &a, &b };
ok(sensors[0].data() == 42);
ok(sensors[1].data() == 52);
}
☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.