オブジェクト指向
プログラミング入門
ソフトウェア基礎講座 第10回
2011年4月14日
服部健太
2011/4/14
オブジェクト指向プログラミング入門
10 2
多重継承の例:不適切な導入例
 TEACHER と STUDENT の 2 つから継承したクラス
TEACHING_ASSISTANT
 実は(より特殊なケースである)反復継承
TEACHER STUDENT
TEACHING_
ASSISTANT
UNIVERSITY_
PERSON
2011/4/14
オブジェクト指向プログラミング入門
10 3
例:飛行機は資産といえるか?
 クラス AIRPLANE
 passenger_count, altitude, position, speed, take_off, etc…
 クラス ASSET
 purchase_price, resale_value, depreciate, resell, etc…
class COMPANY_PLANE inherit
PLANE; ASSET
feature
… …社用機に特有の特性
end
AIRPLANE ASSET
COMPANY
_PLANE
2011/4/14
オブジェクト指向プログラミング入門
10 4
例:数値と比較可能な値
 COMPARABLE のすべての子孫が NUMERIC の子孫ではない
 例: STRING クラスは,辞書順などで比較可能
 NUMERIC のすべての子孫が COMPARABLE の子孫ではない
 例:行列集合は全順序関係を持たない
COMPARABLE NUMERIC
INTEGER
REAL
DOUBLE
2011/4/14
オブジェクト指向プログラミング入門
10 5
例:ウィンドウは木構造であると同
時に長方形でもある
 WINDOW クラスの特性
 階層構造のメンバーとしてのウィンドウ
 サブウィンドウ,親ウィンドウ,サブウィンドウの数,サブウィン
ドウの追加 , etc
 図形オブジェクトとしてのウィンドウ
 高さ,幅, x 座標,表示,隠蔽,変形
class WINDOW inherit
TREE[WINDOW]
RECTANGLE
feature
… …特定のウィンドウ特性
end
2011/4/14
オブジェクト指向プログラミング入門
10 6
複合図形
class COMPOSITE_FIGURE inherit
FIGURE
LINKED_LIST[FIGURE]
feature
…
display is -- すべての構成要素を順番に表示する
do
from start until after
loop
item.display; forth
end
end
…
end
2011/4/14
オブジェクト指向プログラミング入門
10 7
政略結婚(実装継承)
 顧客による方法( STACK2 )りもシンプルになる
class ARRAYED_STACK[G] inherit
STACK[G]
ARRAY[G]
… rename …サブ句がここに入る
feature
full: BOOLEAN is
do Result := (count = capacity) end
put(x: G) is
require not full
do
count := count + 1
array_put(x, count)
end
…
end
*
STACK
ARRAY
ARRAYED_
STACK
2011/4/14
オブジェクト指向プログラミング入門
10 8
構造継承
 あるクラスに,そのクラスを表す基本の抽象
的概念以外にもいくつかの性質があることを
明記したい
 例:オブジェクトの構造を永久的なものにする
STORABLE
 例:数値であると同時に保存可能である
 例:比較可能であると同時にハッシュ可能である
 多重継承なしには無理
2011/4/14
オブジェクト指向プログラミング入門
10 9
機能継承
 継承することで,ある機能を得ることができ
るようになる
 例:履歴機能をカプセル化したクラスを継承する
ことで,ツールのクラスに履歴機能を持たせるこ
とができる
 例:クラス X をテストする場合,テストに役立つ
メカニズムをカプセル化したクラス TEST と X の
両方から継承したクラス TEST_X を定義する
 顧客関係を使って実現することもできる
2011/4/14
オブジェクト指向プログラミング入門
10 10
特性の改名
 多重継承によって,名前の衝突が生じうる
 クラス内では1つの名前は1つのことを意味しなければならな
い
 継承先で改名する
class SANTA_BARBARA inherit
LONDON rename foo as fog end
NEW_YORK rename foo as zoo end
feature
…
end
LONDON NEW_YORK
SANTA_
BARBARA
foo
foo→fog foo→zoo
foo
2011/4/14
オブジェクト指向プログラミング入門
10 11
改名と再宣言
 再宣言では特性は変わるが,名前は変わらない
 別の実際の特性を同じ特性名で参照できる
 意味的なメカニズム
 改名では名前は変わるが,特性は変わらない
 同じ特性をクラスによって別の名前で参照できる
 構文的なメカニズム
 両方使うことも可能
class SANTA_BARBARA inherit
LONDON
rename foo as fog
redefine fog end
…
2011/4/14
オブジェクト指向プログラミング入門
10 12
構造をフラットにする
 継承を多用すると,継承構造が込み入って見にくく
なる
 フラット形式(開発環境のツールによって生成され
る)
 inherit 句は全体が削除される
 そのクラスの特性の宣言と再宣言はすべてそのまま
 継承された特性すべてに対して,親からコピーして宣言が
追加される
 それぞれの継承された特性には, from ANCESTOR とい
う形式のコメント行が追加される
 継承されたルーチンの完全な事前条件と事後条件が再構築
される
 すべての親の不変表明を and することで完全な不変表明が
再構築される
2011/4/14
オブジェクト指向プログラミング入門
10 13
反復継承
 祖先を共有する
 クラス B とクラス C から多重継承するクラス D
があり,この2つの親はどちらもクラス A の後継
者
D
B C
A A
D
(2) 直接的
(1) 間接的
2011/4/14
オブジェクト指向プログラミング入門
10 14
共有と複製
 共有
 反復祖先から継承されてきた特性は同一の特性
 複製
 反復祖先から継承されてきた特性は別個の特性
 C++ では共有か複製かを決めるのはクラス単
位
反復子孫では,同じ名前で継承された反復継承特性は同一特性を表す.異な
る名前で継承された特性は,共通する祖先のオリジナルから複製された別個
の特性を表している
反復継承規則
2011/4/14
オブジェクト指向プログラミング入門
10 15
例:大陸間移動ドライバ
class FRENCH_US_DRIVER inherit
FRENCH_DRIVER
rename
address as french_address,
violation_count as french_violation_count,
pay_fee as pay_french_fee
end
US_DRIVER
rename
address as us_address,
violation_count as us_violation_count,
pay_fee as pay_us_fee
end
feature
…
2011/4/14
オブジェクト指向プログラミング入門
10 16
例:大陸間移動ドライバ
FRENCH_US
_DRIVER
FRENCH_
DRIVER
US_
DRIVER
DRIVER
age
address
violation_count
pass_birthday
pay_fee
pay_fee→pay_french_fee
violation_count
→french_violation_count
address→french_address
pay_fee→pay_us_fee
violation_count
→us_violation_count
address→us_address
(DRIVER)
(FRENCH_US_DRIVER)
age
address
violation_count
age
french_address
french_violation_count
us_address
us_violation_count
2011/4/14
オブジェクト指向プログラミング入門
10 17
改名規則
クラス特性のファイナルネームには次のケースがある
 ● 直接特性(クラス内で宣言される特性)の場合,宣言された名前がファ
イナル
  ネームである
 ● 継承された特性が改名されない場合,親クラスにおけるその特性のファ
イル
  ネームに等しい(再帰的に)
 ● 特性が改名された場合,改名によってついた名前がファイナルネームで
ある
定義:ファイナルネーム
同じクラス内で異なる2つの有効特性が同一のファイナルネームを持っては
ならない
シングルネーム規則
2011/4/14
オブジェクト指向プログラミング入門
10 18
再定義の衝突
 継承経路のどこかで反復継承さ
れた特性が再定義されたとする
 D では利用できる f のバリエー
ションが 2 つ存在する
 B から継承した再定義版
 C からのバージョン
 D においてどちらを利用する
か? D
B C
A
f++
f
2011/4/14
オブジェクト指向プログラミング入門
10 19
共有での衝突:未定義化と結合
 未定義化
 undefine 句を使う
class D inherit
B
C
undefine f end
feature
…
 結合
 2つの別の特性を統合す
る
class D inherit
B
C
rename g as f
undefine f end
feature
…
 両方を redefine してもよ
い
D
B Cf g
2011/4/14
オブジェクト指向プログラミング入門
10 20
複製における衝突:選択
 D は A の特性 f から2つの別々の特性を得る
 名前の衝突はないが,動的束縛で問題が生じる
 型 A の多相的エンティティ a1 が,実行時に D のインスタ
ンスにアタッチされたとき,呼び出し a1.f では何が実行さ
れるか?
 select 句を使う
class D inherit
B
C
select f end
feature
…
D
B C
A
f→bf++
f
2011/4/14
オブジェクト指向プログラミング入門
10 21
select 句の使い方
 rename, undefine, redefine といった句の後に置く
 そのクラスの真の子孫ではそれを繰り返す必要はな
い
 すべてを選択する場合, select all が使える
SOME_PARENT
select all end
あるクラスが,反復祖先の特性の,別個の有効バージョンを複数継承してい
て,しかもどれも再定義しない場合, select 句でその中の1つを必ず選ばな
ければならない
選択( selection )の規則
2011/4/14
オブジェクト指向プログラミング入門
10 22
進んだ例:ウィンドウのバリエー
ション
 境界線とメニューの両方を持ったウィンドウ
WINDOW
WINDOW_
WITH_BORDER
WINDOW_WITH_
BORDER_AND_MENU
WINDOW_
WITH_MENU
display
2011/4/14
オブジェクト指向プログラミング入門
10 23
例:オリジナルクラス WINDOW
class WINDOW inherit
…
display is
-- ウィンドウを表示する
do
…
end
… …他の特性
end
2011/4/14
オブジェクト指向プログラミング入門
10 24
例:境界線付きウィンドウ
class WINDOW_WITH_BORDER inherit
WINDOW
redefine display
end
feature -- 出力する
display is
-- ウィンドウと境界線を表示する
do
Precursor
draw_border
end
feature {NONE} -- 実装する
draw_border is do … end
…
2011/4/14
オブジェクト指向プログラミング入門
10 25
例:メニュー付きウィンドウ
class WINDOW_WITH_MENU inherit
WINDOW
redefine display
end
feature -- 出力する
display is
-- ウィンドウとメニューを表示する
do
Precursor
draw_menu
end
feature {NONE} -- 実装する
draw_menu is do … end
…
2011/4/14
オブジェクト指向プログラミング入門
10 26
うまくいかない例
class WINDOW_WITH_BORDER_AND_MENU inherit
WINDOW_WITH_BORDER
redefine display end
WINDOW_WITH_MENU
redefine display end
feature
display is
-- ウィンドウと境界線を表示する
do
Precursor {WINDOW_WITH_BORDER}
Precursor {WINDOW_WITH_MENU}
end
…
end
2011/4/14
オブジェクト指向プログラミング入門
10 27
正しいバージョン
class WINDOW_WITH_BORDER_AND_MENU inherit
WINDOW_WITH_BORDER
redefine display
export {NONE} draw_border end
WINDOW_WITH_MENU
redefine display
export {NONE} draw_menu end
feature
display is
-- ウィンドウと境界線を表示する
do
Precursor {WINDOW}
draw_border; draw_menu
end
…
2011/4/14
オブジェクト指向プログラミング入門
10 28
反復継承と総称性
 特性が仮総称パラメータを含む場合
class A[G] feature
f: G; …
end
class B inherit
A[INTEGER]
A[REAL]
end
 クラス B で f は共有だがどちらの型か?
反復継承規則によって共有される特性の型,もしくはその特性がルーチンの
場合には,引数の型すべては,反復継承元であるクラスの総称パラメータで
あってはならない.
反復継承での総称性規則
2011/4/14
オブジェクト指向プログラミング入門
10 29
名前の規則
 再定義に Precursor(…) を使う場合,ケース N3 だけがあいまい
さを引き起こす
 その場合, Precursor{PARENT}(…) と書くことであいまいさを
なくす必要がある
多重継承によって得られたクラスでは,異なる親から継承された2つの特性
が同じファイナルネームを持つとき,名前の衝突が起こる.
次のケースのいずれかの場合以外は,名前の衝突を起こしたクラスは違法と
なる
  N1 ● 2つの特性は共通の祖先から継承していて,その祖先のバージョン
から
  の継承経路において,どちらも再宣言されていない.
  N2 ● 2つの特性は互換性のあるシグネチャを持っており,そのうちの1
つは少 
  なくとも暫定形で継承されている
  N3 ● 2つの特性は互換性のあるシグネチャを持っており,どちらもその
クラスで
  再定義される
名前の衝突:定義と規則

オブジェクト指向入門10