Nm

目次

Blog 利用状況

書庫

日記カテゴリ

継承について

継承(+委譲)について考えていきます

今回は、継承についての最初ということで、継承について現在私が考えているもの、これから求めていこうと思うものをざっくり出します
各項目の詳細な説明は次回以降ということにします。
(一応最低限の情報は載せるので実際にやるかどうかは気分しだいということで)
最近数学を見だしたばかりなので、数学用語等間違いがあれば主旨を変えない程度に変更する可能性は高いです

 

#1, 単一継承は多重継承の一形態ではないか
class C : public A, public B{}; //AとBを多重継承したC
class C : public A{}; //Aと無名の型を多重継承したC = 単一継承

//class C : public A, public 無名の型{/*中身は空*/}; //単一継承は←と同じと考える。Cは何も継承しなければ空集合とする

 

#2, 継承に使える要素
継承という仕組みに使えるのは集合のみだとします。(なぜかは、まだよくわからない)
これ以降、集合の特性を使います。
最も重要な特性は、"全ての集合は、ある条件を持つ"ということです
この条件のことを以後制約と呼びます

 

#3, 階層構造<-->制約 の変形
継承は、階層構造を持ちますが、これがどうにも扱いにくかったので制約の形に置き換えます
(相対パス(階層)<-->絶対パス(制約)のイメージ。継承で扱う階層は全て包含だとします)

ここに、ある集合の包含階層  A->B->C があるとします

これを制約表記(私の独自用語:おそらく何か専門用語があるはず)に置き換えます。(単に積集合を適用します)
$A : Aの制約を持つ = A    = $Aの制約
$B : Aの制約とBの制約を持つ = A かつ B  = $Bの制約
$C : Aの制約とBの制約とCの制約を持つ = A かつ B かつ C = $Cの制約

包含階層のAとCは階層が違うため演算ができません。
A->B->CにおけるCの制約は(A かつ B かつ C)であって、Cの制約は必要条件に過ぎないため、
Cの制約だけではCであることを表せず、AとCを同一の空間で扱うことができません

$A,$B,$Cなら、階層を気にせず扱うことができます

 

#4, Aであること及び、AかつBをオブジェクト指向に適用してみる
@1, Aならば、A'という必須なインターフェースを持つ
@2, Bならば、B'という必須なインターフェースを持つ

@3, Aならば、A''という(インターフェース以外の全ての)制約を満たす
@4, Bならば、B''という(インターフェース以外の全ての)制約を満たす

@1,@2,@3,@4が真のとき、
@5(AかつB)ならば (A'のインターフェースを持つ かつ B'のインターフェースをもつ)が真
@6(AかつB)ならば (A''の制約を満たす かつ B''の制約を満たす)が真
ここまではOKなのですが、次はどうでしょうか。

@7(A'のインターフェースを持つ かつ B'のインターフェースをもつ)ならば(AかつB) が真???
逆は必ずしも真ならずであり、@7は必ずしも真ではありません

@7は、@1,@2があってもなくても関係ないとき、つまりA'',B''が恒真のときのみ真です

@1も@3もAの必要条件です。
わざわざ分けたのは、プログラム言語がそうしていることが多いというだけです。
@1と@3をあわせると、"Aであるための全ての制約"と呼べます。
要はAであるための必要十分条件です

 

#5, 項目#4の、@1と@3の違い
インターフェースは、集合を分割する基準を持つことを表すことはできますが
分割された集合を選択することができません

例えば"赤色のもの"という型を作りたい時
X:"赤色かどうかという関数を持つ集合"と、Y:"赤色であるという集合"は同じ集合ではありません
X=赤い集合+赤くない集合 (赤色が何かということは知っている)
Y=赤い集合 (赤色が何かということは知っている)

制約という表現で言い換えると、
X=赤色かどうかという関数を持つという制約 という一つの制約を持つ集合
Y=赤色かどうかという関数を持つという制約と、赤色であるという制約という二つの制約を持つ集合

"赤色のもの"という型を作りたい時は、当然(XかYかでいえば)Yでなければいけません。

 

#6, AかつBとは、実装多重継承である
AとBが完全に別な時(独立している時?)、AかつBは実装多重継承を表します
しかし、現在のオブジェクト指向による継承の仕組みでは、インターフェースによる制約にしか対応していません。
だからインターフェース以外に制約があった時、現在のオブジェクト指向では実装多重継承は、
継承により必要な制約を引き継げないので、うまくいかないことが多いという予測が立ちます

項目#1より、単一継承は多重継承の特殊な形と考えた時、この問題は単一継承でも起こるはずです。

 

#7, インターフェース継承とは、AもしくはBの(IF以外の制約が)恒真のときのAかつBである
(c.制約 = (A.制約 && true))
オブジェクト指向言語によるインターフェースは実装のない関数を指します。
インターフェース以外の制約が恒真であることは、この実装のない関数、インターフェース継承で表すことができます

現在のオブジェクト指向ではこの"片側が恒真"という場合に必要なものを全てもっているので、
インターフェース継承はうまくいくことが多いと予測できます

 

#8, Aの全ての制約とBの全ての制約が同じ時、つまりAかつAの時はどうか
俗にis-aと呼ばれているものです。リスコフの置換原則も同じですかね?
現在のオブジェクト指向ではインターフェースは全て引き継がれるので、
おそらくインターフェース以外の全ての制約が同じであることをさしているのだと思います

Aが真のとき、AかつAは真になりますから、理屈としては正しいです

問題は、現在のオブジェクト指向(だけ)でこれを守るのは現実的に不可能であるということです
AとBがずれた時に検知する仕組みがないこと、そもそもAであることを示せないことが原因です

 

#9, Aの必要十分条件
オブジェクト指向では、Aの制約を表すことができません
ではここで仮に、Aという集合の制約をXとおいてみます

制約に含まれるものは全て、条件を満たすか満たさないかの2値、boolで表すことができます
条件がどれだけあっても、それらを全て積で重ね合わせれば、たった一つのboolとして表すことができます

Aという集合の制約Xは、一つのbool変数としておくことができます
全ての(少なくとも継承の可能な)要素は、一つのbool変数を持たなければいけません

bool変数とboolを返す関数は(多分数学的に)同等なので、boolを返す関数をおきましょう

オブジェクトがこの特殊な意味を持った boolを返す関数を含むのであれば、
インターフェースだけで "あるオブジェクトである"ということを示すことができます

Aであることが表すことができるようになれば、AかつBを表すことができるようになります
つまり、この仕組みを使えば、実装継承が可能になるはずです

 

うーーん。
まあそもそも全ての集合は、集合の条件をもつので、クラスを集合としておくのであれば、
全てのクラスはクラス(集合)の条件を表すboolを返す関数(もしくは同等の何か)を持たなければいけない、とするだけでも十分なのかもしれません。

投稿日時 : 2009年3月12日 2:25

コメントを追加

# re: 継承について 2009/03/12 10:31 インドリ

これは質問なのですが、インターフェイスって値域は同じなのでしょうか?
それによって継承の定義が変ってくるような・・・
インターフェイスの場合、あくまで「約束事」なので、値域が違うような気がします。

# re: 継承について 2009/03/12 13:32 aetos

> Cは何も継承しなければ空集合とする

ちゃいますよね?

# re: 継承について 2009/03/14 15:25 あるふ

>>インドリさん
うーん。質問の意図がまったくつかめません。
インドリさんが理解している範囲を教えてもらえるとまた違うのですがどうでしょうか

インターフェースは、関数名が同じで値域の違う関数の集合です
ここでのインターフェースは、インターフェース継承で使われる関数、つまり実装のない関数をさすとします
#5で何かわからないところがありますか?

関数名および戻り値といったものが「約束事」であれば、
値域も「約束事」のひとつですよね。値域を「約束事」と見てはいけない理由がありますか?



関数名および戻り値がまったく同じにも関わらず、定義域(値域)が違うものであれば
(広義の)インターフェース(=型)として別物であるということを認められますか?
もし認められるのならそれが私が値の定義と呼んでいたものです
値域を変えるだけで別の型と呼べるのなら、単なるエラー処理を新しい動的型(動的型判定)とみなすことも可能になってきます


でもどちらかとえば本文は、関数ではなく、"クラスの定義域(値域)"の話なんですよ
インターフェイスの値域という質問自体が、無関係ではないにしろかなりずれているような気がします。(最終的に関数にも応用するので同じといえば同じなんですが)

インターフェースという単語がかなり多義的になってきたので、
そろそろ名前をつけて区別したほうがいいですね。ちょっと考えます


>>aetosさん
> Cは何も継承しなければ空集合とする
とりあえずCを使ってはいけないところに使ってしまったのがミスでした
ちょっと手直ししてみます

class C : public A{// //単一継承
B
};


//class D : public A, public 無名の型(Bと大体同じ){/*中身は空*/}; //単一継承は←と同じと考える。Dは何も継承しなければ空集合とする


大体あってると思うんですが、#1に関してはあんまりちゃんと考えてないので、まだ問題がありそうです

# re: 継承について 2009/03/16 14:55 aetos

えっと…
クラス=集合とし、集合の要素=インスタンスとする、んですよね? ここから認識が違いますか?

空集合とは、「あらゆる集合の部分集合であり、要素を持たない集合」のことです。
つまり、空集合をクラスに当てはめると、「あらゆるクラスのサブクラスであり、インスタンスを持たないクラス」ということになります。

# re: 継承について 2009/03/19 16:50 インドリ

質問の意図ですが、それは・・・インタフェースの会社の仕方によって継承における集合表現が変るからです。
集合でオブジェクト指向を語る場合、継承とは、親クラスAから派生した子クラスBとCの積集合だと定義される事が多いです。
この記事でも継承が一つのキーポイントになっていると受け取りました。
というのも、空集合を使ってでも継承を多重継承だと定義しているからです。
という事は、集合における多重継承のあり方を考えなくてはなりません。
そこで多重継承に視点を置いて考えてみました。
多重継承の集合操作に於いて熟慮するべきなのは、インタフェースによる値域を共有しない継承です。
値域を共有する普通のクラス継承は積集合ですから集合操作を容易に行う事ができます。
しかし、インタフェースが値域を共有しないとなれば、どうやって集合演算をするのでしょうか?
もし集合演算が適用できないオブジェクト指向ならば、オブジェクト指向を集合理論にする事にどのような有用性があるのか私には分かりません。


あるふさんの説明によると、値域はやはり違うようなので、どうやら集合演算が出来ないようです。
さらには、関数は定義域に含まれないという解釈ですよね?
でもオブジェクト指向はデータ+関数なのです。
その関数を否定しデータだけに着目するのならば実用性が低いと私は感じてしまいます。
それに、関数に集合理論を適用できれば、関数合成だとか色々出来るのに非常に勿体無いです・・・

纏めますと、「どのように集合理論を適用するのか」という点と、オブジェクト指向を集合論で定義する事により産まれる「メリット」が知りたいのです。
あるふさんはどのようなメリットがあると考えておりますか?

# re: 継承について 2009/03/19 17:14 インドリ

分かり難いと思いますので追記します。

>//class C : public A, public 無名の型{/*中身は空*/}; //単一継承は←と同じと考える。Cは何も継承しなければ空集合とする

この記述は値域の和集合でオブジェクト指向を再考するという事ですよね?
全てのクラスを和集合として定義するのか、クラスを積集合+αで考えるのかは大きな違いがあります。
だから私は気にしているわけです。

# re: 継承について 2009/03/26 2:40 あるふ



>>aetosさん
>>クラス=集合とし、集合の要素=インスタンスとする、んですよね?
はい。これはそのとおり。
ただし、同じ認識かどうかは怪しいので確認してもらえますか?

まず、インスタンスはクラスの要素ですが、基本的には集合であると考えています
クラス=A集合とし、クラスのインスタンス= (A集合の要素 かつ B集合)
(調べた限り、集合の要素が集合であってもかまわないですよね)


そして、クラス=集合なのは確かだとは思っているのですが、
何の集合なのかは意見が違う可能性が高いですね

私の解釈では、(少なくともc++における)クラスは、そのクラスを知る集合です
クラス = クラスの条件を満たす集合 + クラスの条件を満たさない集合 = クラスの条件を知る集合

全事象 = クラスの条件を知らない集合 + クラスの条件を知る集合(クラスの条件を満たす集合 + クラスの条件を満たさない集合)

ここの"全事象"という視点から見ると、私は排中律を認めていない立場みたいです。
(ちょっと自信がないですが、直感主義?多値論理?。まだあまり区別が付いてない)
もう少しちゃんと言うと、排中律を使用するためには条件がある、という感じで捉えています。


>空集合
これはよくよく考えたら先の私のコメントの方の間違いのようです。
むしろ逆に全事象とか未定義?の方が近かったです。
(全事象 &= (A & B) と、&=で全事象制限するイメージ。)
ただまだ混乱しているので、これに関してはまだ後で変更するかもしれません




>> インドリさん
>>継承とは、・・積集合だと定義される事が多いです。
私もそう定義します
問題は、現在のオブジェクト指向(だけ)ではそれができていないし、
実際のところ現在のオブジェクト指向(だけ)の継承では和集合に近いものになっているように感じているということです

積集合を表現するためには、別の何かが必要です。
少なくともクラスの値域を表現する方法がなければ無理ではないかと思うんですよね



>>あるふさんの説明によると、値域はやはり違うようなので、
これは違いますね。
広義になるかもしれませんが、私のテーマは、値域(定義域)をさしています

関数が値域を持つのは当然として、
クラスという集合の値域、インスタンスという集合の値域を表現できなければおかしいんじゃないの?ってことです
現在のオブジェクト指向という枠では表現できませんよね

全ての集合が値域を持ち、クラス(インスタンス)が集合なら、全てのクラス(インスタンス)は値域を持ちます。
(全てではなくても実用的な大部分の集合ということでもOK)

それなら共通基底クラスで定義して、全てのクラスに値域を取得するインターフェースを持たせるのは自然な発想ですよね
今のオブジェクト指向からは外れてしまいますけど。


>//class C : public A, public 無名の型{/*中身は空*/}; //単一継承は←と同じと考える。Cは何も継承しなければ空集合とする
これに関しては、"空集合"の表記はどうやら間違いのような気がしてきたのですが
ちょっとわからなくなってきたので、ここについては保留ということでお願いします

# re: 継承について 2010/07/06 17:51 tiffany

X:"赤色かどうかという関数を持つ集合"と、Y:"赤色であるという集合"は同じ集合ではありません
X=赤い集合+赤くない集合 (赤色が何かということは知っている)
Y=赤い集合 (赤色が何かということは知っている)
http://www.thomassabosales.com/thomas-sabo-charms.html
http://www.tiffanyesale.com/

# re: 継承について 2010/08/09 12:49 buy pandora beads

関数が値域を持つのは当然として

# re: 継承について 2010/08/09 12:50 pandora bracelets

あるふさんの説明によると、値域はやはり違うようなので

# re: 継承について 2010/08/09 12:50 pandora jewelry sale

実際のところ現在のオブジェクト指向(だけ)の継承では和集合に近いものになっているように感じているということです

# VlNhxlPibIEOvNM 2012/01/06 22:11 http://www.luckyvitamin.com/c-1147-vitamin-b12

Not bad post, leave it at my bookmarks!...

タイトル
名前
URL
コメント