クラスの継承

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

クラスの継承

#1 投稿記事 by 淡幻星 »

いつもお世話になっております。

下記のように、継承クラスは違うが追加されるメソッドは同じである
クラスを定義する場合、もっと上手い方法は無いものでしょうか?
同じメソッドの定義を二度書くのはどうかと思いまして・・・。

コード: 全て選択

Class ObjA
	Inherits BaseObjA
Public
	Function Hoge() As Long
		'追加メンバの定義。ObjAもObjBも同じ物。
		Hoge = TRUE
	EndFunction
End Class

Class ObjB
	Inherits BaseObjB
Public
	Function Hoge() As Long
		'追加メンバの定義。ObjAもObjBも同じ物。
		Hoge = TRUE
	EndFunction
End Class
OverTaker
記事: 231
登録日時: 2005年5月31日(火) 17:14
お住まい: 茨城県

#2 投稿記事 by OverTaker »

それって、スーパークラスとサブクラスを逆にしてはまずいでしょうか?

コード: 全て選択

'上のコードとは、淡幻星さんが投稿されたコードです。

Class BaseObj
Public 
    Function Hoge() As Long 
        '上のコードでいう追加メンバをスーパークラスに
        Hoge = TRUE 
    EndFunction 
End Class 

Class ObjA
    Inherits BaseObj
Public 
	'上のコードでいうBaseObjAのメンバ定義
End Class

Class ObjB
    Inherits BaseObj
Public 
	'上のコードでいうBaseObjBのメンバ定義
End Class
Tomorrow
記事: 72
登録日時: 2005年6月04日(土) 10:09

こんな方法もあります

#3 投稿記事 by Tomorrow »

共有したいメソッドを別のクラスに宣言して、使う側のクラスでインスタンスを作って呼び出すというのはどうでしょう。

Decoratorパターンなんかで使われる方法です↓
http://itpro.nikkeibp.co.jp/article/COL ... 13/227227/

コード: 全て選択

'共通メソッド用のクラス
Class Obj
Public
	Function Hoge() As Long
		'追加メンバの定義。ObjAもObjBも同じ物。
		Hoge = TRUE
	End Function
End Class


Class ObjA
	Inherits BaseObjA
Public
	Function Hoge() As Long
		Dim o As Obj	'インスタンス作成
		Hoge = o.Hoge()	'メソッド呼び出し
	End Function
End Class


Class ObjB
	Inherits BaseObjB
Public
	Function Hoge() As Long
		Dim o As Obj	'インスタンス作成
		Hoge = o.Hoge()	'メソッド呼び出し
	End Function
End Class
最後に編集したユーザー Tomorrow [ 2006年4月09日(日) 11:29 ], 累計 1 回
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

Re: クラスの継承

#4 投稿記事 by 7 »

安易な考えですけどこんなのはどうでしょう。

コード: 全て選択

Class ProtoObj
	Function Hoge() As Long
		Hoge = TRUE
	End Function
End Class

Class BaseObjA
	Inherits ProtoObj
Public
'	BaseObjAのメソッドを定義
End Class

Class BaseObjB
	Inherits ProtoObj
Public
'	BaseObjBのメソッドを定義
End Class

Class ObjA
	Inherits BaseObjA
End Class

Class ObjB
	Inherits BaseObjB
End Class
もう一つ。

コード: 全て選択

Class Hoge
	Function Hoge() As Long
		Hoge = TRUE
	End Function
End Class

Class ObjA
	Inherits BaseObjA
Public
	Function Hoge() As Long
	Dim h As Hoge
		Hoge=h.Hoge()
	End Function
End Class

Class ObjB
	Inherits BaseObjB
Public
	Function Hoge() As Long
	Dim h As Hoge
		Hoge=h.Hoge()
	End Function
End Class
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

≫OverTaker様

#5 投稿記事 by 淡幻星 »

早々のレスをありがとうございます。
OverTakerさん さんが書きました:> それって、スーパークラスとサブクラスを逆にしてはまずいでしょうか?
サブクラスの追加メソッド内部で、
スーパークラスのメソッドを利用しているので、難しいです・・・。
(蛇足ですが。メソッドとメンバとをまた間違えてました、私^^;)

情報が足りなかったですね。すいません。
以下のようなメソッドの参照関係にある継承になります。

コード: 全て選択

Class BaseObjA
Public
    Function Method1() As Long
        Method1 = TRUE
    EndFunction
End Class

Class BaseObjB
    Inherits BaseObjA
Public
    Function Method2() As Long
        Method2 = FALSE
    EndFunction
End Class

'-------------------------------------

Class ObjA
    Inherits BaseObjA
Public 
    Function Hoge1() As Long 
        '追加メンバの定義。ObjAもObjBも同じ物。
        Hoge1 = Method1() 'スーパークラスのメソッドを参照
    EndFunction 
End Class 

Class ObjB
    Inherits BaseObjB
Public
    Sub ObjB()
        'コンスタラクタだけは継承クラスにあわせて変更される。
        Dim r As Long
        r = Method2()
    EndSub
    Function Hoge1() As Long 
        '追加メンバの定義。ObjAもObjBも同じ物。
        Hoge1 = Method1() 'スーパークラスのメソッドを参照
    EndFunction 
End Class 

ABではたしか利用できなかったと思いますが、
仮想基本クラス+多重継承の概念を使えば、

コード: 全て選択

Class BaseObjA
    Function Method1() As Long
End Class

Class BaseObjB
    virtual Inherits BaseObjA
Public
    Function Method2() As Long
End Class

'-------------------------------------
Class ObjA
    Inherits BaseObjA
Public
    Function Method1() As Long '追加メソッドはここにのみ記述
End Class 

Class ObjB
    Inherits BaseObjB
    Inherits ObjA
Public
    Sub ObjB()
    'こちらのクラスでは継承とコンスタラクタの対応のみを行う。
End Class 
となるところでしょうか?(ちょっと自信ない^^;)
多重継承を導入する予定は無い、という話だったと思います。インターフェースはよく分かりません/汗)


・・・見れば分かるように、クラスObjBがクラスObjAの機能をほぼ内包するわけで、
だったらクラスObjAは無くても良いじゃないか、と言われれば確かにそうなのです。
なので、絶対必要というわけではないのですが^^;
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

≫Tomorrow様 ≫7様

#6 投稿記事 by 淡幻星 »

≫Tomorrowさん
Tomorrowさん さんが書きました:> 共有したいメソッドを別のクラスに宣言して、使う側のクラスでインスタンスを作って呼び出すというのはどうでしょう。
なるほど。
メソッドの定義を書くのを一回だけにできますね・・・と思ったんですが、
スーパークラスのメソッド利用が、やっぱ障害になっちゃいますね・・・。
(詳細は、上記の私のレスを参照ください)


≫7さん
うーん。上記の私のレスが理由で、難しいです。


質問時の情報が足らず、すいませんでした。m(_ _)m
無理にObjB、ObjAとクラスを作り分けるのを止めた方が賢いのかもしれませんが・・・^^;
Tomorrow
記事: 72
登録日時: 2005年6月04日(土) 10:09

コンポジションでは?

#7 投稿記事 by Tomorrow »

> サブクラスの追加メソッド内部で、
> スーパークラスのメソッドを利用しているので、難しいです・・・。
> (蛇足ですが。メソッドとメンバとをまた間違えてました、私^^;)
>
> 情報が足りなかったですね。すいません。
> 以下のようなメソッドの参照関係にある継承になります。
↓のようにObjBのフィールドにObjAのインスタンスを持たせて(コンポジション)、ObjAのメソッドを呼び出すようにしてはどうでしょう?
なぜこのような継承ツリーにしているのか、その意図が理解できていませんので、これでうまくいくかわかりませんけど。

ちなみに
Java/C# <=> C++
メソッド <=> メンバ関数
フィールド <=> メンバ変数
なのでメソッドもメンバの一種だと思っています。

コード: 全て選択

Class BaseObjA
Public
	Function Method1() As Long
		Method1 = TRUE
	EndFunction
End Class

Class BaseObjB
	Inherits BaseObjA
Public
	Function Method2() As Long
		Method2 = FALSE
	EndFunction
End Class

'-------------------------------------

Class ObjA
	Inherits BaseObjA
Public 
	Function Hoge1() As Long 
		'追加メンバの定義。ObjAもObjBも同じ物。
		Hoge1 = Method1() 'スーパークラスのメソッドを参照
	EndFunction 
End Class 

Class ObjB
	Inherits BaseObjB
Private
	objA As ObjA
Public
	Sub ObjB()
		'コンスタラクタだけは継承クラスにあわせて変更される。
		Dim r As Long
		r = Method2()
	EndSub
	Function Hoge1() As Long 
		Hoge1 = objA.Method1() 'ObjAのメソッドを参照
	EndFunction 
End Class
> ABではたしか利用できなかったと思いますが、
> 仮想基本クラス+多重継承の概念を使えば、
(中略)
> (多重継承を導入する予定は無い、という話だったと思います。

検索してみたらこんなサイトがありました。

http://www.cmagazine.jp/src/kinjite/cpp ... tml#index1
http://ysserve.int-univ.com/sugsi/Lectu ... 04-04.html
淡幻星さんが示したコードは菱形継承と呼ばれるみたいですね。
多重継承の問題点というか、あまり好ましくない使用例みたいです。
上のサイトには、
具体的にはクラスの中に,別クラスのメンバ変数を必要なだけ「所有」し,それで多重継承の代用が可能だということです。
とも書かれています。

> インターフェースはよく分かりません/汗)
インターフェイスの使い方についてAB風に(といってもまだサポートされてないですが)記述してみると、こんな感じになります。
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

Re: コンポジションでは?

#8 投稿記事 by 淡幻星 »

> なぜこのような継承ツリーにしているのか、その意図が理解できていませんので、
機能A,Bを持っているクラスに機能Cを追加したクラスと、
機能Aのみを持っているクラスに機能Cを追加したクラス、
というようように、機能を全て持ったクラスと、機能を限ったクラスというように、
作り分けたいのです。大に小を兼ねさせたくないというか。
もっとも、これはコード作成側の希望であって、
利用側にとっては大が小を兼ねていれば十分という気はします。


う~む。見ていると、継承よりもインスタンスを生成する方が
(この手法をコンポジションって呼ぶのですか?)好まれているみたいですね。
> なのでメソッドもメンバの一種だと思っています。
ですか。どうもですw
> インターフェイスの使い方についてAB風に(といってもまだサポートされてないですが)記述してみると、こんな感じになります。
ありがとうございます。
インターフェースの内容は分かりましたが・・・便利さがイマイチ実感できません^^;
オーバーライドと同類っぽい?
まぁ、そこは使っていく中で覚えるものだと思いますけど。
Tomorrow
記事: 72
登録日時: 2005年6月04日(土) 10:09

Re: コンポジションでは?

#9 投稿記事 by Tomorrow »

> 機能A,Bを持っているクラスに機能Cを追加したクラスと、
> 機能Aのみを持っているクラスに機能Cを追加したクラス、
> というようように、機能を全て持ったクラスと、機能を限ったクラスというように、
> 作り分けたいのです。大に小を兼ねさせたくないというか。
機能と実装を分けるBridgeパターンに解決策のヒントがありそうです。
(詳しくは↓を見てください。)
http://itpro.nikkeibp.co.jp/article/COL ... 13/227227/
http://www.techscore.com/tech/DesignPattern/Bridge.html
http://www.hellohiro.com/pattern/bridge.htm

つまり、機能A,B,Cなどをインターフェイスで表現し、それを継承して具体的な処理内容を記述するクラス(実装側)と、インターフェイスを組み合わせて提供する機能を定義するクラス(機能側)に分けるといったイメージです。
(わかりづらいですねw。↑のサイトにあるクラス図の方がわかりやすいと思います。)
> もっとも、これはコード作成側の希望であって、
> 利用側にとっては大が小を兼ねていれば十分という気はします。
うーん…。利用側が使いやすいように、というのがオブジェクト指向の思想のようです。(と思っています)
あまりにも機能が多いと使うのも大変なので、利用側のメリットも無きにしもあらず、な気はしますが。
> う~む。見ていると、継承よりもインスタンスを生成する方が
> (この手法をコンポジションって呼ぶのですか?)好まれているみたいですね。
インスタンスを生成することではなく、「フィールドにインスタンスを持つ」ことがコンポジションであると理解してます。
オブジェクト指向のツボ ~Vol6. コンポジション~

インスタンスを生成するのは、「処理をほかのクラスに任せる」ということで委譲というみたいです。
またコンポジションのことをhas-a関連や集約と呼ぶこともあるようです。
> インターフェースの内容は分かりましたが・・・便利さがイマイチ実感できません^^;
> オーバーライドと同類っぽい?
> まぁ、そこは使っていく中で覚えるものだと思いますけど。
インターフェイスは継承元の中身がないだけでオーバーライドと変わりない仕組みですよね。
違いはインターフェイスを継承してオーバーライドすることは中身のないメソッドの処理の中身を作ることというわけで「実装」と呼ぶ程度のものです。

「便利さ」ですか…。
インターフェイスを使うとクラス間の結びつきが緩くなり、部品として再利用しやすくなるというのがメリットだといわれています。

こちらもまだまだ勉強不足で実践的にインターフェイスを使ったことはありません。
なのでプログラムとしての動作がわかる程度ですし、実際どのような場面で使うと効果的なのかといったことはわかりません。
とりあえずデザイン・パターンの理解がインターフェイスの理解の早道だと思っています。
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

Re: コンポジションでは?

#10 投稿記事 by 淡幻星 »

> 機能と実装を分けるBridgeパターンに解決策のヒントがありそうです。
そうですね。
一番の近道はBridgeパターンみたいですね。
と言っても、私は、Tomorrowさんのレスで初めてその存在を知りましたがw
しかし難しい・・・。
仕組みは分かったつもりですが、いざ実装するとなるとコードがイメージできません^^;
トライアンドエラーしていくしかないですね。
もっとも、現在のABはまだインターフェースはサポートしてないですから、
これは将来に、という話ですか。

なお、質問自体に関しては「大は小を兼ねる」にすることにしました^^:
メソッド実装をいくらか変えることで、納得できる程度に機能を減らせましたので。
お騒がせ致しましたm(_ _)m


> 違いはインターフェイスを継承してオーバーライドすることは中身のないメソッドの処理の中身を作ることというわけで「実装」と呼ぶ程度のものです。
オーバーライドの便利さは、
「実装しなくても使える。新たに実装することもできる。」だと思ってますが、
インターフェースの「実装できる」は・・・やっぱりイマイチ分かりません。
まぁ、こういうものの便利さは、必要に迫られたときに初めて実感するものだと
思いますから、今は「そういう概念(手法)がある」と覚えておけば十分かな~、
ということで、逃げることにします(^^;)


Tomorrow様、いろいろとありがとうございました。
返信する