これはなかなか寝付けない夜にとりとめもなく考えていた空想であり、そのまま考えていては朝になってしまうので強制的に打ち切った思考の断片である。
人間を、年齢層と性別で分けることを考える。
|
年齢層 |
| 10歳未満 |
10代 |
20代 |
30代 |
… |
| 性別 |
男 |
|
|
|
A |
|
| 女 |
|
B |
|
|
|
この表全体を「人間クラス」としたとき、AおよびBは何か。
まず、年齢層や性別を人間クラスのプロパティとし、AやBが入っている表のセルをインスタンスであると考えてみる。
すると、こうなる。
enum 年齢層 { 10歳未満, 10代, 20代, 30代, 以下略 }
enum 性別 { 男, 女 }
class 人間 { 年齢層 age, 性別 sex }
人間 A = new 人間(); A.age = 年齢層.30代; A.sex = 性別.男;
人間 B = new 人間(); B.age = 年齢層.10代; B.sex = 性別.女;
表の列も行もセルも、すべてクラスであると考えると、こうなる。
class 人間 {}
class 10歳未満の人間 : 人間 {}
class 10代の人間 : 人間 {}
class 20代の人間 : 人間 {}
class 30代の人間 : 人間 {}
class 男 : 人間 {}
class 女 : 人間 {}
class 10歳未満の男 : 10歳未満の人間, 男 {}
class 10歳未満の女 : 10歳未満の人間, 女 {}
中略
class 30代の男 : 30代の人間, 男 {} // A
class 10代の女 : 10代の人間, 女 {} // B
ただし、これは素朴には、こういうことがありうる。
class 矛盾した人間 : 10代の人間, 20代の人間, 男, 女 {}
先にずらずらと列挙した例では、例えば「20代の男」は「20代、かつ、男」であった。
すると、この矛盾した人間は、「10代であり20代、かつ、男であり女」になってしまう。
現在の多重継承が可能な言語では、こういうクラスを作ることができてしまう。
だが、意図したところは、「年齢層から1つ、性別から1つを多重継承する」である。
コンパイルエラーにするにはまだ練り足りないが、もう少しだけ意図を追加してみる。
例えば C# の属性風に。
// 人間の具象派生クラスは、年齢層と性別から1つずつを多重継承すること!
abstract class 人間 {}
[ ClassCategory( "年齢層" ) ] abstract class 10歳未満の人間 : 人間 {}
[ ClassCategory( "年齢層" ) ] abstract class 10代の人間 : 人間 {}
[ ClassCategory( "年齢層" ) ] abstract class 20代の人間 : 人間 {}
[ ClassCategory( "年齢層" ) ] abstract class 30代の人間 : 人間 {}
[ ClassCategory( "性別" ) ] abstract class 男 : 人間 {}
[ ClassCategory( "性別" ) ] abstract class 女 : 人間 {}
class 10歳未満の男 : 10歳未満の人間, 男 {}
class 10歳未満の女 : 10歳未満の人間, 女 {}
中略
class 30代の男 : 30代の人間, 男 {} // A
class 10代の女 : 10代の人間, 女 {} // B
さらに C# の延長として、System.Type から複数の親クラス情報を、カテゴリ別に取得できると想定してみよう。
Type type = typeof( 30代の男 );
Type ageType = type.BaseTypes[ "年齢層" ]; // ageType == typeof( 30代の人間 );
Type sexType = type.BaseTypes[ "性別" ]; // sexType == typeof( 男 );
ここで唐突に、C# から JavaScript にターゲットを変えてみる。
といっても、これまでの流れから明らかなように、JavaScript チックな実在しない空想言語である。
JavaScript では、実行時にプロトタイプを変更することができる。
これは、C# のような静的型付けの言語では、親クラスの変更に相当するだろう。
では、多重継承に相当するように、プロトタイプを複数持つことができたとしたら? ついでに、それが JavaScript お得意の名前つきマップだとしたら?
こんな形になるんじゃないだろうか。
(面倒なのでクラス定義を一部省略した)
function 人間() {}
function 30代の人間() {}
30代の人間.prototype = new 人間();
function 男(){}
男.protptype = new 人間();
function 30代の男() {}
30代の男.prototypes[ "年齢層" ] = new 30代の人間();
30代の男.prototypes[ "性別" ] = new 男();
この JavaScript モドキのコードと、一番最初に挙げた C# モドキのコードを見比べてみる。
ちょっと変更して再掲しよう。
人間 30代の男 = new 人間();
30代の男.age = 年齢層.30代;
30代の男.sex = 性別.男;
実によく似た形をしている。
…というところまで考えて寝た。