クラスや構造体のメンバのpublic, privateとは #
(クラスや構造体に関して)public、privateは多くの言語でクラスや構造体のメンバを別のコードから参照できるかどうかを意味する。
つまり、
class MyClass{
public:
int a; // public
int b; // public
private:
int c; // private
bool d; // private
};
というクラスがあった時、
int main(){
MyClass x;
int z = x.a; // OK publicなので アクセスできる
bool e = x.d; // NG(コンパイルエラー) privateなのでアクセスできない!
return 0;
}
のように別コードからMyClass
の実体x
を通してメンバ(フィールドとも呼ばれる)にアクセスできるかどうかということだ。
この例ではa
, b
はアクセスできるが、c
, d
はアクセスできない。
Getter、Setterとは #
それぞれ、ゲッター、セッターと読む。
厳密な定義は知らないが、具体的にどんなもののことを言っているのかというと、
struct DeviceCommandBuffer {
pub is_dummy_device: bool, // public
buffer: Vec<u8>, // private
priority: u32, // private
// ...
}
impl DeviceCommandBuffer {
pub fn buffer(&self) -> &[u8] {
&self.buffer
}
pub fn set_priority(&mut self, new_priority: u32) {
const MAX_PRIORITY:u32=0xffff;
if MAXPRIORITY < new_priority {
panic!();
// もしくはResultを返すとか
}
self.priority = new_priority;
}
pub fn priority(&self) -> u32 {
self.priority
}
// ...
}
のようなコードがあるとして、
getterは fn buffer
と fn priority
のようなクラスや構造体のメンバの値を取得する関数のことを指す。
setterは fn set_priority
のようなクラスや構造体のメンバに値をセットする関数のことを指す。
getter は 読み、setter は 書きだ。
Getter, Setterを実装すべきかどうか #
考えられるうち、有用なパターンとしては、
- 完全にパブリックにする C++の
public
、Rustのpub
- プライベートにしてGetterのみを定義する
- プライベートにしてSetterのみを定義する
- プライベートにしてSetterとGetterを定義する
- 完全にプライペートにする C++の
private
、Rustではデフォルト
だ。
パブリックにするのであれば、ゲッターもセッターも迂回できてしまうので実装する必要はなくなる。
3のSetterのみについては俺の経験では実装を考えたことはない。
もしかしたらそういった状況があるのかもしれないが。
比較より、それぞれの利点や使いどころまとめたほうが良いと思ったのでそうする。
上のDeviceCommandBuffer
が先進的な自動医療手術で麻酔薬を投与する際に使われるコードだと仮定する。
麻酔を入れすぎると患者がホトケになると想定。
何を言いたいのかというとそのくらいの緊張感を持って考えるということ。
プライベートにしてGetterのみを定義する #
ライブラリのユーザーなどが不用意に重要な変数を弄ってしまうことを防ぐことができる。
デバッグビルドにだけGetterに範囲チェックのassertionを入れてバグを見つける可能性を高めるなんてこともできる。
privateなのでassertionは必ず通ることになる。
Getterの関数名はget_xyz()
かxyz()
が多い。(自分は後者のほうが好み。)
プライベートにしてSetterとGetterを定義する #
これだったら完全にパブリックにしてしまえと言う人もいるが、setterで数値の範囲チェックなどの入力値の検証を行うこともできる。
もちろん、有効な値でしか生成できない構造体や型を定義してそれを利用してpublicにすることもできるが。
完全にプライペートにする #
外に全く晒す必要のない変数はこれでok。
自分の場合、今のところは分からないという場合はprivateにしておいて必要になったらgetterを実装するなり、publicにするなりしている。
結論 #
絶対にこうしておけばおkなんてことはない。
状況に応じて決断しよう。
特にライブラリなどの使い回されるコードを書いている場合は、ユーザーが間違った使い方をしないようにしてあげると良いと思う。
(自分のプログラムでコアな部分を書いている時に迷って考えたのでまとめた。)