第13回
ポリモーフィズム
種類の違うものを、同じ手続きで扱う。
基本
IMU imu;
GPS gps;
Sensor* sensors[2];
sensors[0] = &imu;
sensors[1] = &gps;for (int i = 0; i < 2; i++) {
sensors[i]->update();
}それぞれのオブジェクトのupdate()が呼ばれる。ループを書く側は、中身がIMUなのかGPSなのかを知る必要がない。
マイコンでの応用
例えばセンサの種類が変わっても、
Sensor* sensor;として扱える。これにより、上位の制御コードをセンサの具体的な種類から分離できる。センサを別の製品に載せ替えても、上位のコードは書き換えずに済む。
Controller ← Sensorの種類を知らない
│
↓
Sensor* ← 共通インターフェース
│
┌─────┴─────┐
↓ ↓
IMU GPS注意点
組み込みシステムでは、動的メモリ確保や仮想関数を無条件に多用するのではなく、
- RAM使用量
- Flash使用量
- 実行時間
- リアルタイム性
- メモリ断片化
なども考慮する必要がある。
動かして確かめる
演習に入る前に、まずこのサンプルを動かして結果を見る。追加の部品は要らない。光るのはボードに載っている内蔵LEDで、それ以外はシリアルモニタの出力で確かめられる。code/examples/13-polymorphism/を開き、pio run -t uploadで書き込んでからpio device monitorで出力を見る(手順と、外付けのLEDなどをつなぐ場合は開発環境にまとめてある)。
code/examples/13-polymorphism/
├── include/
│ ├── Sensor.hpp
│ ├── IMU.hpp
│ ├── GPS.hpp
│ └── ToF.hpp
└── src/
├── IMU.cpp / GPS.cpp / ToF.cpp
└── main.cpp Sensor* しか出てこない// 第13回:種類の違うセンサを、同じ手続きで扱う
//
// loop() は中身が IMU なのか GPS なのか ToF なのかを知らない。
// センサを1種類増やすとき、loop() を1文字も変えずに済むことを確かめる。
#include <Arduino.h>
#include "GPS.hpp"
#include "IMU.hpp"
#include "Sensor.hpp"
#include "ToF.hpp"
IMU imu;
GPS gps;
ToF tof(6); // センサはつないでいない。ピン番号は保持するだけ
// 上位のコードは「Sensorであること」しか知らない
Sensor* sensors[] = {&imu, &gps, &tof};
const int SENSOR_COUNT = sizeof(sensors) / sizeof(sensors[0]);
void setup() {
Serial.begin(115200);
delay(1000);
Serial.print("センサの数: ");
Serial.println(SENSOR_COUNT);
}
void loop() {
for (int i = 0; i < SENSOR_COUNT; i++) {
sensors[i]->update();
sensors[i]->print();
}
Serial.println();
delay(1000);
}センサの数: 3
IMU roll=0.50 pitch=0.20
GPS lat=35.6587 lon=139.7455
ToF distance=375.00 mm
IMU roll=1.00 pitch=0.40
GPS lat=35.6588 lon=139.7456
ToF distance=350.00 mm確かめること。
loop()の中にIMUもGPSもToFも出てこない。Sensor*しか出てこない- 4種類目のセンサを足して、
loop()を書き換えずに済むことを確かめる sizeof(sensors) / sizeof(sensors[0])で個数を求めている。この手間は第16回で消える- 種類ごとに
ifで分けて書いた場合、センサが増えるたびにどこが伸びるかを考える
演習:センサを配列でまとめて更新する
IMU/GPS/ToFをSensor*の配列に入れるloop()で全センサを一括更新する- センサを1種類追加したとき、
loop()側を書き換える必要があるかを確認する