wiredBeep - gblog

gblog: generalized blog または「愚ブログ」

2008-02-28

[] C++における共変戻り値と反変引数 23:14

近々、wikiの「C++まにあっく」のほうに書きたい話の下書き。

共変戻り値と反変引数とは

オブジェクト指向において、共変、反変というと、こういうことです。

  • クラス HogeBase の派生クラスが HogeDerived
  • クラス FugaBase の派生クラスが FugaDerived

とします。このとき、

  • HogeBase → HogeDerived と変更するとき FugaBase → FugaDerived と変化するのが「共変」
  • 反対に FugaDerived → FugaBase と変化するのが「反変」

です。

C++の場合、メソッドの戻り値を共変にすることができます。つまり

class HogeBase {
    virtual FugaBase* method();
};
class HogeDerived : public HogeBase {
    virtual FugaDerived* method();
};

のように、戻り値が違っても共変であれば、HogeDerived::method() が HogeBase::method() をオーバーライドできます。

HogeDerived::method() がたとえ HogeBase::method() として実行されたとしても、戻り値を FugaDerived → FugaBase とアップキャストすれば良いだけなので、大丈夫というわけです。

一方、メソッドの引数を共変にすると、ダウンキャストが必要になるので、安全ではありません。安全なのは反変な引数です。

class HogeBase |
    virtual void method(FugaDerived*);
};
class HogeDerived : public HogeBase {
    virtual void method(FugaBase*);
};

たとえ HogeDerived::method() が HogeBase::method() として実行されたとしても、やはりアップキャストしか起こらないので安全です。

反変引数の使いどころ

ところが、C++は反変引数をサポートしていないようです。確かにあまり用途が見つからないので仕方ないかなと思っていましたが、ひとつ有用かもしれない場合を見つけました。

template で mix-in」というテクニックがあります。

template <typename T>
class MixIn : public T {
    // ...
};

というクラスを用意することで、任意のクラス T に必要な機能を追加する mix-in を作製できるというものです。

さて、ここで mix-in としては邪道な使い方かもしれませんが、この MixIn 内で

template <typename T>
class MixIn : public T {
    virtual void method(FugaBase*);
};

というメソッドを用意し、T::method() をオーバーライドすると仮定します。T は任意のクラスなのでオーバーライドするメソッドは

  • T::method(FugaDerived*)

かもしれませんし

  • T::method(FugaDerived2*)

かもしれません。

この場合には反変な引数が必要となります。

…無理やりだなあ。

2008-01-26

[][] MoinMoinちょっと更新 23:29

最近、gblogはどちらかというと日記、ニュースに特化させたいと思っている。つまり、あまり時期に寄らない話題は、beeplex.net 本体に書いていくので、ここの更新が少なくても、許していただきたいのだ。beeplex.net 本体は (サーバーPythonにPyXMLが入っていないために) RSSに対応していないので利便性に欠けるが、日記形式よりWikiの方が適していると感じている。

Wikiエンジンとして使用している MoinMoin はソースコードを色付け表示できるようになっているが、デフォルトでは対応言語が少ない。

OCaml用はparser/ocaml.py - MoinMoinから落としてきた。これをいじってSmalltalk用を作製し、ともにbeeplex.netのMoinMoinに適用した。今のところいい感じで色付けしてくれているようだ。

2007-12-22

[] Mono 15:17

Mono をインストールしてみました。Monoって言ってもいろいろありますが、いわゆる、.NET Framework 互換環境の Mono です。

から1.2.6を落としてきいの、インストールしいので、まったく問題なく動きます。

公式サイトのチュートリアルをやってますが、いい感じですね。

チュートリアルでは、プログラムの実行は

mono hello.exe

と書けと書いてますが、HelloWorld程度なら、Gtk# を使わないものはそのまま

hello.exe

で動くみたい。

さて、IDEはどれがいいのだろう。

SharpDevelop

Mono用にIDEとして、SharpDevelop 2.2 を落としてきました。

これはすごい。UIは VisualStudio 以外の何者でもない。VisualStudio を使い慣れた人なら、何の問題もなく開発できるでしょう。むしろ、フォームのデザイナ・コードの切り替えがタブになっているので、逆に使いやすいともいえます。「おぉぉ!」という感嘆の声が止まりませんでした。

日本語入力も問題なさそう。ソースコードに日本語を含めると、UTF-8で保存しますか、と聞かれるので yes と答えておけば、問題なく表示された。デバッグも出来るし、これさえあればC#での開発は十分、という感じ。

とにもかくにも、C#、Mono、Winforms を使えば、Windows、Linux、MacOS X のマルチプラットフォームで開発が簡単に、しかもフリーソフトウェアだけで出来るわけで。いい時代になったものです。

2007-10-25

[][] あくまで夢 00:18

こんなものが作りたいなあ…。

  • WindowsとLinuxの両方でGUIバリバリ。
  • お手軽に作れるの。
  • 自分が必要としているもの。

さて、何だろう? 言語としては、

  • C#

  • WindowsならMicrosoft .NET Framework上で
  • LinuxならMonoかDotGNU Portable .NET上で

実行…というのが良いだろうか? 今、しっかりとしてもので欲しいのは (そして良いものがないのは)

  • バイナリエディタ
  • 家計簿

かなあ。

まあ、あくまで夢ですが。

バイナリエディタ作りたいなあ。

2007-09-22

[] インスタンスとオブジェクトはどう違うか 13:08

プログラミングコラム連載第二回。連載していたと、私も今知った。

コラムと銘打っているので正しいことが書いてある可能性は限りなく低いです。FLT_EPSILON くらい低い。ということで、信じないでください。ただし、実務でオブジェクト指向してるひとの実感ではある。


さて、「インスタンス」という言葉と「オブジェクト」という言葉の違いが分からないという話を良く聞く。そこから初めて、オブジェクト指向のいろいろを騙ろうという企画。

確かに、C++で「string型のオブジェクト」と「stringのインスタンス」が同じものを指していれば、違いが分からないのは当然だよね。まずは直訳してみよう。

  • オブジェクト=対象
  • インスタンス=実例

ということを前提に、C++Smalltalkの場合を比べてみたい。C++

string("hello")

と書いて生成されるのが、hello という文字列を表すオブジェクト。このオブジェクトは同時に string という名前のクラスのインスタンスと呼ぶ。

Smalltalkでは、文字列リテラル自体がStringクラスのインスタンスになるので、

'hello'

という感じ。これで生成されるのは、同じく、hello という文字列を表すオブジェクトで、Stringクラスのインスタンス。

ここまでは同じなんだけど、Smalltalkがちょっと違うのはここから。C++のstringはクラスであって、オブジェクトではない。intなどのクラスではない型と同じような扱いということ。

一方、SmalltalkではStringクラスもオブジェクトだ。この仕組みに明るくない方は、えっ? と思われるかもしれない。クラスとは、クラス変数 (=静的データメンバ) やクラスメソッド (=静的メンバ関数) を、そのクラスのインスタンス変数 (=データメンバ) やメソッド (=メンバ関数) とした、グローバルに生成されたオブジェクトなのだ。Stringクラスに纏わるさまざまな処理がまとめられたもの考えても構わない…かもしれない。

クラスもオブジェクトということは、そのクラス、つまり、クラスのクラスもあるということ。これを「メタクラス」と呼ぶ。'hello'のクラスはString。Stringのクラスは、Stringメタクラス (String class という名前がつく) ということ。

メタクラスもやはりクラスなので、オブジェクトだ。メタクラスもオブジェクトなので、メタクラスにもクラスが存在する。メタクラスのクラスは Metaclass という名前だ。Metaclass クラスもオブジェクトなので……という関係がどこまでも無限に続いている。

と、ここまで言うと、C++的 (=Java的=C#的=内部を気にしないRuby/Python的) なオブジェクト指向に慣れていらっしゃる方々は余計混乱するかもしれない。鶏が先か、卵が先か? と。

これは、「まずクラスがあって、それを元にインスタンスが作られる」という文化に慣れているためだ。「クラス=型」という概念が原因になっている。

教科書的な言い方では、「オブジェクト "hello" はクラス string のインスタンスだ」というのは「オブジェクト "hello" はクラス string に属している」と言い替えられる (実務では聞いたことが無いが)。そもそも、クラスとは日本語で「種別」というような意味だ。

概念的には、「同じ機能を持つモノ (=オブジェクト) は同じ種類 (=クラス) だ」と言える。

実装的には、「同じ機能を持つオブジェクトの処理もまとめて行うのがクラスだ」となる。

つまりは、「まず string というクラスがあって、そこから "hello" というオブジェクトが生成される」よりは、「まず、String というオブジェクトと 'hello' というオブジェクトがあって、その関係性として『'hello' は String に属する』と決める」とでも言ってしまった方が良い。

実装的にはメモリイメージを知るためにはクラスの定義が…とも言えるが、C++な方はこう考えてはいかがだろう?

  • Stringクラスとはそれぞれのオブジェクトの仮想関数テーブルのこと
  • 文字列のメモリイメージと仮想関数テーブルへのポインタをまとめて1つのオブジェクトにする='hello' を String に属させる

ここまでくると、インスタンスとオブジェクトでは、概念の種類が違うということが分かっていただけるかと思う。

  • オブジェクト=ポリモーフィズムを通して操作する対象…では端折りすぎだろうか。次回は「オブジェクト指向とは」にしようか。
  • インスタンス=「属している」の逆を表す関係性

「インスタンスである」というのはオブジェクトなどに対する形容だというわけ。


オブジェクトなど…と言ったのには理由があって、C++に簡単な「オブジェクトとは関係ないインスタンス」が存在するからだ。その名は「テンプレート」。

template <typename T>
    AClassTemplate;
AClassTemplate<int> an_object;

ここでは、AClassTemplate という名前のクラステンプレートを作成し、テンプレート引数 T=int としてオブジェクト an_object を作成している。ここで、

  • クラス AClassTemplate<int> は、クラステンプレート AClassTemplate のインスタンス
  • オブジェクト an_object は、クラス AClassTemplate<int> のインスタンス

と呼ばれる。クラステンプレートは <int> のように、実際の型などを指定して初めて一人前のクラスになるが、これを「テンプレートのインスタンス化」とか「インスタンシエイト」(instantiate) と呼ぶ。テンプレートの実例なのだから、正しい命名だ。


公理的集合論との対応を考えれば簡単だ。

  • オブジェクト=元
  • クラス=(部分)集合
  • オブジェクト a はクラス b のインスタンス= a∈b
  • クラス b はクラス c の派生クラス=クラス c はクラス b の基底クラス= b⊂c

公理的と言ったのはSmalltalkの「クラス=オブジェクト」が公理的集合論の「集合=元」と対応するのが面白いとおもったから。


途中で触れたが、次回のテーマは「そもそもオブジェクトとはなんぞや」。

この記事はただのたわごとです。私の直感以外、なんの根拠も有りません。信じたために不利益を被っても責任はおいかねます。