DOBON.NET どぼん!のVB道掲示板(プログラム)過去ログ

異なるクラスのインスタンスを1元管理したい

Class1 を継承して、Class2、Class3 を作った場合で
Dim Ent(1) As Object
Ent(0) = New Class2
Ent(1) = New Class3
のように、1つの配列に保持しておいて
Ent(0).Class2Item = xx
Ent(1).Class3Item = xx
みたいに使いたいのですが、上記でも動くようですが
IDEでのコーディング時には当然、ENT() から
Class2ItemやClass3Itemは見えませんし
オブジェクト指向的に、好ましくない気がします
使うときに
Dim Ent2 As Class2
Ent2 = Ent(0)
Ent2.Class2Item = xx
のようにすれば、少しはわかり易くなりますが...

よい方法があれば、アドバイスいただけませんか。
Kamaliと言います。以後よろしく。
.NETは素人ですが、C++, Javaをよく使っています。

>Class1 を継承して、Class2、Class3 を作った場合で
>Dim Ent(1) As Object
>Ent(0) = New Class2
>Ent(1) = New Class3
>のように、1つの配列に保持しておいて
>Ent(0).Class2Item = xx
>Ent(1).Class3Item = xx
>みたいに使いたいのですが、上記でも動くようですが
>IDEでのコーディング時には当然、ENT() から
>Class2ItemやClass3Itemは見えませんし
>オブジェクト指向的に、好ましくない気がします

いえ、好ましくないなんてことは全然ありません。このような使い方はオブジェクト指向プログラミングの好例ともいえます。これが出来ないとオブジェクト指向言語を使う意味そのものが無いのに等しいですからね。
それから、

Dim Ent(1) As Class1

でもいいと思いますよ。いや、この方が正しいコーディングというべきか…。

>使うときに
>Dim Ent2 As Class2
>Ent2 = Ent(0)
>Ent2.Class2Item = xx
>のようにすれば、少しはわかり易くなりますが...
>
>よい方法があれば、アドバイスいただけませんか。

後は、オブジェクトの設計に関ってくる問題だと思うのですが、、、
うーむ、.Class2Item, .Class3Itemというのが、、、気になりますねえ。
単にこれはコーディング例として、そのようなプロパティ(それとも「メンバー」と呼んでいるのかな?)があったとして、、という話ならいいのですが・・・。

.Class2Item, .Class3Itemが「意味的」に同じ操作であるならば、Class1に.ClassItemというプロパティーを定義して、Class2, Class3はそれと同じ名前で微妙に違ったそれぞれの固有の実装を組込むのが正しい設計になります。
つまり、どういうことかというと、あなたが一番やりたいと思っている
 「これらを区別しないで、同様に扱いたい」
ということを実現するためにこそ、オブジェクト指向があり、あなたはそのためにClass1を継承させた、Class2, Class3を作ったのではないですか?ということです。だから、これらが全く同じに見えるように、メソッドもプロパティーも、その中でやっている処理内容が異なっていても、それを区別しようと、異なる名前にするのではなく、同じ名前にするのです。

異なる名前にしてしまっては、本来のオブジェクト指向の恩恵に預かれなくなってしまうのです。
Kamaliさん、アドバイスありがとうございます。
>.NETは素人ですが、C++, Javaをよく使っています。
最近VB.NETはじめたんですが、オブジェクト指向になかなか馴染めなくて...

>Dim Ent(1) As Class1
>でもいいと思いますよ。いや、この方が正しいコーディングというべきか…。

まさに、そんなふうにできないかと質問しました
ここで、Class2Item、Class3Item は、Class2 Class3 固有のプロパティやメソッドのことです。
したがって、単にDim Ent(1) As Class1 とした場合、Ent(0).Class2Itemにアクセスできないから、Dim Ent(1) As Objectにしていましたが。

Dim Ent(1) As Class1
Dim Ent2 As Class2
Ent(0) = New Class2
Ent2 = Ent(0)
Ent2.Class2Item = xx

のように、ENT(0).Class2Itemに直接アクセスできないけど、Ent2を通してClass2Itemにアクセスするのが良いという意味でしょうか。
Class2型変数にClass3型を代入できないけど、Class2型変数にClass1型を代入できるところが、継承ということでしょうか。

> 「これらを区別しないで、同様に扱いたい」
>ということを実現するためにこそ、オブジェクト指向があり、あなたはそのためにClass1を継承させた、Class2, Class3を作ったのではないですか?ということです。だから、これらが全く同じに見えるように、メソッドもプロパティーも、その中でやっている処理内容が異なっていても、それを区別しようと、異なる名前にするのではなく、同じ名前にするのです。

Class2 Class3 で必要なプロパティや空のメソッドをすべて、Class1に用意しておいて、Class2 Class3 でオーバーライドするという意味でしょうか。
その場合、Class2 には不要なClass3用のプロパティがくっついてくるのでは?
不要なメンバーは、プロテクトでシャドウするとかっていうのもヘンですよね?..
>>Dim Ent(1) As Class1
>>でもいいと思いますよ。いや、この方が正しいコーディングというべきか…。
>
>まさに、そんなふうにできないかと質問しました
>ここで、Class2Item、Class3Item は、Class2 Class3 固有のプロパティやメソッドのことです。
>したがって、単にDim Ent(1) As Class1 とした場合、Ent(0).Class2Itemにアクセスできないから、Dim Ent(1) As Objectにしていましたが。
>
>Dim Ent(1) As Class1
>Dim Ent2 As Class2
>Ent(0) = New Class2
>Ent2 = Ent(0)
>Ent2.Class2Item = xx
>
>のように、ENT(0).Class2Itemに直接アクセスできないけど、Ent2を通してClass2Itemにアクセスするのが良いという意味でしょうか。

そういうことは意味していませんが、多分そうしか出来ないでしょう。

>Class2型変数にClass3型を代入できないけど、Class2型変数にClass1型を代入できるところが、継承ということでしょうか。

.NETは素人なのでVB.NETで本当にそうできるのかどうか確かめたわけではありません。でも、C++, Javaと同じとすればそうなります。

>Class2 Class3 で必要なプロパティや空のメソッドをすべて、Class1に用意しておいて、Class2 Class3 でオーバーライドするという意味でしょうか。
>その場合、Class2 には不要なClass3用のプロパティがくっついてくるのでは?
>不要なメンバーは、プロテクトでシャドウするとかっていうのもヘンですよね?..

一方で必要でもう一方で不要というのであれば、このような設計はしません。
Class2, Class3がとても似通っていて、共通の特性をいっぱい持っているとき、
はじめて、Class1という親クラスを用意し、そこに共通のものを持たせるという
ことに意味が出てくるのです。
しかし、当然共通にならないものも出てきます。だから、別のクラスになるわけですよね。

さて、ところで、こんなことを議論しても根本的な問題解決にならなさそうです。
DEGさんの当初の質問、「一元管理したい」という目的が私には段々見えなくなってきました。つまり、あなたが一元管理に何を期待しているのかが理解できません。あなたの当初のコーディングに何ら問題はありません。あなたのやり方以外で、クラスごとに異なるメソッドを認識させる方法は恐らく無いと思いますし、C++, Javaでも似たようなことはよくやります。そういう意味では、これ以上説明する事柄は無いのです。
けれども、あなたは「これでは一元管理になっているとは思えない」からこの質問を出したのですよね。
Class2, Class3をまとめて一つの「コレクション」として管理したいというのが目的であれば既にこれで達成されているわけです。そして、これ以上のことを期待しても何も出てきません。各クラスに固有のメソッドやプロパティがあって、それらにアクセスしたいというのであれば、どの種類のオブジェクト指向言語を使っても今と似たようなことをすることになります。

そういうわけで、もしあなたがこれとは違う何かを期待していたのでしたら、もう一度質問を出して下さい。そして、そのときは各クラスについてもっと具体的な説明も加えて下さい。そして、具体的に何がしたいか書いて下さい。各クラスの役割がはっきりしないと、本当の意味でどういうクラス設計が良いのか説明できません。
Kamaliさん、
>DEGさんの当初の質問、「一元管理したい」という目的が私には段々見えなくなってきました。つまり、あなたが一元管理に何を期待しているのかが理解できません。あなたの当初のコーディングに何ら問題はありません。あなたのやり方以外で、クラスごとに異なるメソッドを認識させる方法は恐らく無いと思いますし、C++, Javaでも似たようなことはよくやります。そういう意味では、これ以上説明する事柄は無いのです。

確かに当初のコーディングで動くことは確認済みですし、コレクションする目的も達成されていますが、遅延バインディングになるから、後々わかりにくいかなという思いから、またクラスの知識が乏しいので、動けはOKではなく一般的な手法から見てどうなのかと思い質問しました。

Dim Ent(1) As Class1
で、遅延バインディングは解決したので、これでいこうと思います。

おかげで勉強になりました、ありがとうございました。

DOBON.NET | プログラミング道 | プログラミング掲示板