第8回 解答例
カプセル化する
演習の解答例。まず自分で書いてから読むこと。
Motorクラス
#pragma once
class Motor {
public:
Motor(int pin);
void begin();
void setSpeed(int speed);
int getSpeed() const;
void stop();
private:
void apply(); // 内部だけで使うので private
int pin;
int speed;
};#include <Arduino.h>
#include "Motor.hpp"
namespace {
const int MIN_SPEED = 0;
const int MAX_SPEED = 100;
const int PWM_MAX = 255;
}
Motor::Motor(int pin)
: pin(pin), speed(0) {
}
void Motor::begin() {
pinMode(pin, OUTPUT);
stop();
}
void Motor::setSpeed(int speed) {
if (speed < MIN_SPEED) {
speed = MIN_SPEED;
}
if (speed > MAX_SPEED) {
speed = MAX_SPEED;
}
this->speed = speed;
apply();
}
int Motor::getSpeed() const {
return speed;
}
void Motor::stop() {
setSpeed(MIN_SPEED);
}
void Motor::apply() {
analogWrite(pin, speed * PWM_MAX / MAX_SPEED);
}動作確認
Motor motor(24);
void setup() {
Serial.begin(115200);
motor.begin();
motor.setSpeed(-100000);
Serial.println(motor.getSpeed()); // 0
motor.setSpeed(500);
Serial.println(motor.getSpeed()); // 100
motor.setSpeed(60);
Serial.println(motor.getSpeed()); // 60
}外部から何を渡しても、speedは必ず0〜100に収まる。これがカプセル化の効果である。
「外部に本当に必要な操作」を考える
Motorの場合、外から必要なのは次の3つだけで足りる。
| 操作 | 公開 | 理由 |
|---|---|---|
setSpeed() | public | 速度を指示したい |
stop() | public | 止めたい。よく使うので専用に用意する |
getSpeed() | public | 現在値を知りたい |
apply() | private | PWMへの変換は内部都合。外は知る必要がない |
pin / speed | private | 直接書き換えられると制限を回避できてしまう |
やりがちな誤り
全メンバにgetter/setterを機械的に付けるのはカプセル化ではない。
// 意味のないカプセル化
void setSpeed(int speed) { this->speed = speed; } // 制限がない
int getPin() const { return pin; } // 外は pin を知る必要がないsetSpeed()に制限がなければ、privateにした意味がない。getPin()は内部の都合を漏らしているだけで、誰も使わない。