このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

下層ほど複雑でリッチ -- 型階層

型理論や仕様論は一番好きな話題かもしれないな(背後にあるインスティチューションが好きなんだろうが)。続き物にする気はなかったのだけど、また型理論の話を少し。

昨日のエントリー「もっと型理論」で:

"types as specifications/theories"の立場では、サブタイプ/スーパータイプの定義は複雑になります。


問題は、サブタイプ/スーパータイプ概念が、extendsだけで尽きているわけではないことです。まだ説明すべきことが残っているのです。

と書いたけど、extendsだけも分かること/説明できることは随分あります。それと、少し工夫すると、サブタイプ/スーパータイプ概念をextendsだけで説明することもできるのだった(“工夫”の部分があるから、簡単かどうかは別問題だけど)。

「もっと型理論」で説明した意味で「型」「仕様」「extends」「拡張」などの言葉を使うとして、いま T2 extends T1だとしましょう -- ここで、T1, T2は型(つまり仕様、それは、インターフェース+制約)です。これは次のどちらか、または両方であることを意味します。

  1. [インターフェースの拡張] T2のインターフェース部分は、T1のインターフェース部分を拡張(extend)している。
  2. [制約の拡張(強化)] T2の制約部分(ホーア制約式の集まり)は、T1の制約部分を拡張している。

このとき、「T2はT1のサブタイプである(T1はT2のスーパータイプである)」と言ってかまいません。型階層を図に描くとき、普通はスーパータイプを上のほうに描くので、T1は上位、T2は下位だと言ってもいいでしょう。

下層にいくほど実装は大変になる

この世で一番簡単な仕様(型と同義語)は次です。

spec Any {
 interface {
 }
 /* 制約はない */
}

インターフェースは空っぽで、制約式もなしです。空っぽのインターフェースは「メソッドを持ってはいけない」ということではなくて、「必須のメソッドは特にないよ」という意味なので、どんなクラスでもこの仕様を満たします。つまり、Anyの実装は全然気を使う必要がない、まったくお気楽・勝手気ままなのです。

spec AB {
 interface {
  int a();
  void b();
 }
 /* 制約はない */
}

これはインターフェースが規定されているので、なんでもいいがとにかくaとbの実装は必須です。aとbをどう実装しようと勝手、という点ではやっぱり気楽ですが、仕様を満たす手間がゼロというわけではありません。

spec AB3 {
 interface {
  int a();
  void b();
 }
 [1] (true){}(-1 <= a() && a() <= 255);
 [2] Any(int x) (a() == x){}(a() == x);
 [3] Any(int x) (a() == x){a();/*値は捨てる*/}(a() == x);
}

こうなると、だいぶ気を使います。仕様を満たす労力がそれなりに発生します。もっとメソッドが増えたり、もっと制約式が増えたりすると、どんどん大変になります。

型階層の上下は、実装に使う注意力や労力の多寡

仕様で規定されるメソッドや制約が増えれば増えるほど、それを満たす実装を作るために気を使い、手間がかかることになります。spec Anyが定義する型では、この仕様を満たすための注意力や労力はゼロですよね。そして、この型が型階層の最上位(ルート)に位置します。一番エライけど無視可能な奴だ。

で、まとめれば、こういうこと:

  • サブタイプになるほど定義が複雑になる。
  • サブタイプになるほど、その実装にたくさん気を使い、手間もかかるようになる。