2011年12月6日火曜日

「ぐへへお姉ちゃんパンツ何色」から始めるクラス解説

「ぐへへお姉ちゃんパンツ何色」はこれ以上ないほどオブジェクト指向であり、しかも理想的な実装をしていることに気づきました。これを用いてオブジェクト指向を説明してみようと思います。

ある人が「ぐへへお姉ちゃんパンツ何色」と質問するのは、お姉ちゃんオブジェクトの保持するpants_color変数を取得しようとする手続きと見ることが出来ます。つまり
oneechan.pants_color
を取得しようとしているわけです。
ではどうすればいいのでしょうか?

考えてみましょう。直接パンツを見ればpants_colorを取得することができますね。
クラスを使わないとすればこんな書き方が考えられます。
struct oneechan{
     int pants_color;
};
構造体でひな形を宣言します。そして
oneechan homuhomu;
こんな感じでしょうか。 ほむほむを宣言します。
するとhomuhomu.pants_colorでほむほむのパンツの色にアクセスできます。
しかしこれには致命的な欠点があります。
homuhomu.pants_color = 0xFFFFFF;
……そう、色を勝手に変えられてしまうのです!
たとえばこんなミスをしたらどうなってしまうでしょうか?
if(homuhomu.pants_color = 0x000000){なんかかんか}
パンツの色が黒かどうか確認しようとして、黒のパンツを履かせてしまうという致命的なバグを引き起こしてしまいます!
そのうえ構造体はその性質上、内部の値がすべてどこからでも参照できてしまします!
これは非常によろしくない。そのために、クラスです。
クラスは「カプセル化」として隠蔽の仕組みを備えています。というわけでクラスを用いてひな形を作ってみましょう。
class oneechan{
private:
     int pants_color;
}; 
こうなります。
パンツの色はプライベート変数になったため、
oneechan homuhomu;
homuhomu.pants_color = 0x000000;
こんなコードを書いてもコンパイラが怒ってくれます。
具体的に言うと「お姉ちゃんのパンツの色はプライベートなのでアクセスできないぞっ(意訳)」と叱ってくれるはずです。
これでお姉ちゃんのパンツの色を勝手に変更されてしまう問題は無くなったかに見えます。
けれどももう一つ、別の問題が生まれたことに気づくでしょうか?
  std::cout << std::hex << std::showbase << homuhomu.pants_color << std::endl;
お姉ちゃんのパンツの色を16進数で表示してね!というと……再びコンパイラが「お姉ちゃんのパンツの色はプライベートなのでアクセスできないぞっ」 と怒ります。そう、隠蔽されてしまったパンツの色を確認するにはどうしたらいいのでしょうか?

こうしましょう。
class oneechan{
public:
     int get_pants_color() const;
     void set_pants_color(int color);
private:
     int pants_color;
};

int oneechan::get_pants_color() const {
    return pants_color;
};

void oneechan::set_pants_color(int color) {
    pants_color = int color;
};
 パブリックにset_pants_color()メソッドとget_pants_color()メソッドを追加しました。
パンツの色にアクセスするためにはこのメソッドを利用します。
(2011/12/07追記:getterにはconstを付けるように!との指摘を受けました。ありがとうございます。)
homuhomu.get_pants_color()
これでパンツの色を取得できます。パンツの色はprivate なので「外部から勝手にアクセスする」ことはできません。しかしお姉ちゃん自身からは参照することができるのです。だからお姉ちゃんにいったん質問を投げ、値を教えてもらうという手順をふむのです。

こうしてお姉ちゃんのパンツの色の安全は確保されました。

C++においてクラスの変数は明示的にpublicを付けない限りprivateです。よほど熱心にパンツの色を公開しようとしているお姉ちゃんでない限り、スカートを身につけてパンツの色を隠蔽していますし、勝手に履き替えさせたりしてくれません。

「ぐへへお姉ちゃんパンツ何色」という質問、これは非常に行儀のよい手続きです。まずお姉ちゃんはパンツの色をカプセル化して隠蔽しています。お姉ちゃん本人以外が勝手にアクセスすることはできません。
質問者はそれを理解してお姉ちゃんのプライベートなパンツの色にアクセスするメソッドを「ぐへへお姉ちゃんパンツ何色」「ぐへへお姉ちゃん○色のパンツ履いて」と言って呼んでいるのです。


……ですが注意してください。oneechan::get_pants_color()が実際に何をするかまではわかりません。内部ではoneechan::call_police()と同じ処理をやっている可能性は高いとおもわれます。
また、oneechan::get_pants_color()を利用する際にはnullptrが返ってくる可能性、つまり「履いてません」エラーが出てくる可能性もあるということに……

(2011/12/07追記)
nullptrはintに型変換されないのでコンパイルエラーになるとの指摘を受けました。しかしNULLだと0に変換されるので黒のパンツになってしまう……これもゆゆしき問題です!なんとかしなければ……次の記事までに理想的なお姉ちゃんクラスとパンツの色について考え直すことにします。

まとめです
・お姉ちゃんのパンツの色を表現するのに構造体を使ってはならない(お姉ちゃんは露出狂ではない)
・お姉ちゃんのパンツの色はスカートで隠されている(隠蔽!)
・基本的にお姉ちゃんの情報はprivate(public以外は隠蔽!)
・privateな情報でもお姉ちゃん本人はアクセスできる
・private変数にpublicなメソッドを使ってアクセスする
・関数やメソッドの名前だけで内部の処理を見積もってはならない
・お姉ちゃんは偉大。
・白銀朱音は俺の姉(ry






クラスの重要さはお姉ちゃんのパンツにあらわれていました。
以上!!!

15 コメント:

  1. 面白かった! ちょっと自分のサイトにトラックバック風に書いてみました。http://www.flat7th.org/~keizo/wiki/?page=memo%2F20111206

    返信削除
    返信
    1. 私はsingletonにはすごく意味があると思います。
      「ほとんど意味は無い」はちょっと大げさかなぁと。
      「使う人が気を付ければ良い」という運用ベースでプログラムは
      成り立ちませんからね。それが「保証されている」というのが
      すごく大事な事じゃないですかね。仕様に書くかどうかではなくて。

      削除
  2. パンツ自体もオブジェクトだと考えられますので、
    class pants;
    を定義して、oneechanオブジェクトのprivateメンバとして実装し隠蔽することにより、
    pants.get_size();

    pants.get_type();
    が実装でき、パンツの履き替えやパンツのバージョンアップにも対応できる、より実用的なパンツが実現すると考えられます。

    返信削除
  3. > if(homuhomu.pants.color = 0x000000){なんかかんか}
    pants_colorがpants.colorになってます。

    返信削除
  4. ありがとうございます。訂正しました。

    返信削除
  5. どちらかというと構造体とクラスの違いと隠蔽の説明ってかんじですね。

    しかしこれは参考になる。

    返信削除
  6. お姉ちゃんとfriendなら自由に見られるのでしょうか?

    返信削除
  7. setterについての突っ込みです。
    ぐへへお姉ちゃんパンツ何色 私は黒は穿かない! - GeekなNooblog
    http://d.hatena.ne.jp/sona-zip/20111206/p1

    返信削除
  8. http://d.hatena.ne.jp/laplus-knsn/20111206/1323175234
    JavaScript編書いてみたんですけど、問題あったら消しますのでご連絡ください!

    返信削除
  9. 二匹めのドジョウを狙うブロガー達が今必死になって他言語仕様かプロセス変えただけバージョン作ってんだろうなー
    胸熱

    返信削除
  10. りっちゃんかよw(ネタバレ

    返信削除
  11. rubyバージョン見たいです。

    返信削除
  12. この記事を見て、オブジェクト指向が手続き型より優れているポイントを1つはじめて知りました。
    構造体は自由に読み書きできるが、隠蔽されたデータは自由に読み書きできないことがある。
    しかしそれなら値を書き換える関数や、値を返す関数を作れば同じことなのでは・・・などと思ってしまいます。
    今後も分かりやすい講座をよろしくお願いします。

    返信削除
  13. この記事の本質ではない(C++の)技術的な指摘で申し訳ないですが2点ほど。

    > int oneechan::get_pants_color()

    getterは基本的にconst付けてください。

    int oneechan::get_pants_color() const


    > また、oneechan::get_pants_color()を利用する際にはnullptrが返ってくる可能性、つまり「履いてません」エラーが出てくる可能性もあるということに……

    NULLならともかく、nullptrはintへの暗黙変換はできないので、nullptrを返そうとしたらコンパイルエラーです・・・。

    返信削除
  14. ご指摘ありがとうございました。訂正しました。

    返信削除