C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: 引数のあるコンストラクタしかもたないクラスのオーバーライド


(過去ログ 44 を表示中)

[トピック内 16 記事 (1 - 16 表示)]  << 0 >>

■23500 / inTopicNo.1)  引数のあるコンストラクタしかもたないクラスのオーバーライド
  
□投稿者/ スイカ (1回)-(2008/08/17(Sun) 14:23:25)

分類:[VB.NET/VB2005] 

VB.NET 2003

はじめまして、VB.NETを学び始めたスイカです。

クラスの継承について質問です。

親クラスのコンストラクタを継承し、子クラスでそれをオーバーライドしたい場合、
VBの規則上直接オーバーライドできないので、子クラスのコンストラクタの定義の1行目に
MyBase New()と記述して子クラスのコンストラクタを記述するということは理解しています。

また、親クラスで複数のコンストラクタがある場合(オーバーロードされている)、
子クラスではそのうち引数の持たないコンストラクタのみ継承できるということも理解しています。

そこで質問なのですが、親クラスが引数のあるコンストラクタしかもたない場合
子クラスのコンストラクタはどのように記述すればよいのでしょうか?


コードで書くと下がうまく動くようにしたいとうことです。

よろしくお願いします。


'親クラス
Public Class classOya
Public Sub New(ByVal intValue1 As Integer, ByVal intValue2 As Integer)
'処理1
End Sub

Public Sub New(ByVal strValue1 As String,ByVal strValue2 As String)
'処理2
End Sub
End Class


'子クラス
Public Class classKo
Inherits classOya

Public Sub New((ByVal strValueA As String)
MyBase.New()
'処理A
End Sub
End Class

引用返信 編集キー/
■23503 / inTopicNo.2)  Re[1]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ maruta (1回)-(2008/08/17(Sun) 15:25:36)
文法的にこう書けます、という回答がスイカ様の実現したいモノと
一致するとは限らないと思います。

> コードで書くと下がうまく動くようにしたいとうことです。
この「うまく」、についてもう少し説明を加えた方が
期待する答えを得やすいかもしれませんよ。

で、文法的な話でよろしければ、逆に質問です。

・親クラスのコンストラクタの引数を、子クラスはどのようにして得るのでしょうか?

-> 親クラスと同じように、コンストラクタの引数で得る?なら、
子クラスのコンストラクタに引数が足りなくないでしょうか。

-> 別の方法で(外部ファイルや、デフォルト値、または何らかの計算の結果として)取得する?
なら、子クラスから親クラスのコンストラクタを呼び出す前に、その記述が必要ではないでしょうか。

以上、ご参考になれば幸いです。
引用返信 編集キー/
■23504 / inTopicNo.3)  Re[1]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ やじゅ (542回)-(2008/08/17(Sun) 15:31:19)
やじゅ さんの Web サイト
No23500 (スイカ さん) に返信
>
> '子クラス
> Public Class classKo
> Inherits classOya
>
> Public Sub New(ByVal strValueA As String)
> MyBase.New()
> '処理A
> End Sub
> End Class
>

意味がよく理解できないのですが、
単純にダミーで引数に値を入れるのでは駄目なんでしょうか?

MyBase.New(strValueA, String.Empty) '仮に処理2を動作させる
引用返信 編集キー/
■23505 / inTopicNo.4)  Re[2]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ スイカ (2回)-(2008/08/17(Sun) 16:00:51)
maruta様
早速の回答ありがとうございました。

私はまだ勉強中で知識も少ないことから
説明が分かりにくくなってしまってすみません。

私が目指していることは
子クラスの方では、親クラスと全く異なったコンストラクタを作成したいということです。
親クラスのコンストラクタを引き継ぐというわけではありません。
(手持ちの参考書ではこの場合とりあえずMyBase New()を記述するとあったので
それを参考にコードを作成ました。)
そのため、親クラスのコンストラクタの引数は子クラスで取得しません。

教えていただいた
> MyBase.New(strValueA, String.Empty) '仮に処理2を動作させる
とした場合、1度は継承した親クラスのコンストラクタが動作してしまいますよね?
このコンストラクタの動作を行わずに子クラスで別にコンストラクタを動かしたいのです。

継承せずに別なクラスとして記述すれば済むことですが、
親クラスではメソッドやプロパティを持っており、
それらは子クラスでも継承してそのまま使いたいために継承させたいです。
(コードにこの部分を書き漏れてしまってすみません。)


このような場合、どのようにプログラムを書けばよろしいのでしょうか?


引用返信 編集キー/
■23508 / inTopicNo.5)  Re[3]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ 魔界の仮面弁士 (819回)-(2008/08/17(Sun) 17:11:04)
2008/08/17(Sun) 17:38:13 編集(投稿者)

No23505 (スイカ さん) に返信
> 子クラスの方では、親クラスと全く異なったコンストラクタを作成したいということです。
子クラスと親クラスで、コンストラクタ引数が異なる事は良くあります。

ただ、だからといって、親の引数をどう与えるかで悩んでしまうという事は、
そもそものクラスの設計に、何か問題があるのかも知れません。


> 親クラスのコンストラクタを引き継ぐというわけではありません。
引き継がなくてはいけません。引き継ぐ必要が無いのであれば、それは
初期化の条件からして異なっているという事になるので、そもそもの
クラス分けの設計段階から見直したほうが良いかと思います。

そもそも継承では、"Is-a 関係" を保つ必要があります。すなわち子クラスとは、
常に「親クラスの一種」でなければならないのですが、もしかしたら、
機能的に似ているだけで、意味的には無関係なクラスを継承で処理しようとしてはいませんか?

具体的に、現在どのようなクラスを作っているのかを明記した方が、
より具体的なアドバイスを得られるかと思いますよ。


たとえば、親クラスの
> Public Sub New(ByVal intValue1 As Integer, ByVal intValue2 As Integer)
という定義が、データの範囲を表す「最小値と最大値」を引数に取る
 Public Sub New(ByVal minValue As Integer, ByVal maxValue As Integer)
の意味だったとして、これを子クラスでは「最小値」だけで指定したいとなれば、最大値を補完するために、
 Public Sub New(ByVal minValue As Integer)
  MyBase.New(minValue, Integer.MaxValue)
 End Sub
という実装になりますよね。


> 親クラスではメソッドやプロパティを持っており、
> それらは子クラスでも継承してそのまま使いたいために継承させたいです。
そういう時は、Class A を継承して Class B を作成するのでは無く、
Class A と Class B に、共通の「MustInherit Class C」を継承させたり、
共通の Inteface を Implements させることで対応できるかと思います。


あるいは、本当に両クラスが継承すべき関係にあるのなら、その場合の親クラスには
 Public Sub New(Integer, Integer)
 Public Sub New(String, String)
だけではなく、子クラスから呼び出せるように、引数一つの
 Sub New(String)
あるいは引数なしの
 Sub New()
のいずれかが(Public ではなく、Friend や Protected でも可)実装されているものだと思います。

そしてそれが無いのであれば、その親クラスは、そういった利用のされ方が想定されて
いないのですから、そもそも継承すべき関係では無かった(あるいは逆に、親クラスの実装不足)として
クラス設計を見直した方が良いかも知れません。いずれにせよ、現状のクラス設計を見てみないと何とも。
引用返信 編集キー/
■23509 / inTopicNo.6)  Re[3]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ まどか (575回)-(2008/08/17(Sun) 17:33:54)
No23505 (スイカ さん) に返信
> 子クラスの方では、親クラスと全く異なったコンストラクタを作成したいということです。
> (手持ちの参考書ではこの場合とりあえずMyBase New()を記述するとあったので

作れます。そして、MyBase.Newを呼ばなければよいです。
ただし、基底クラスの初期化をするためにプロパティ変数は通常Protectedにします。

基底クラス
Protected _Name As String
Public Property Name As String
派生クラス
Public Sub New(〜)
    _Name = ""

>>MyBase.New(strValueA, String.Empty) '仮に処理2を動作させる
> とした場合、1度は継承した親クラスのコンストラクタが動作してしまいますよね?
> このコンストラクタの動作を行わずに子クラスで別にコンストラクタを動かしたいのです。

Protected変数にしておけば上書きできますよね?

> 継承せずに別なクラスとして記述すれば済むことですが、
> 親クラスではメソッドやプロパティを持っており、
> それらは子クラスでも継承してそのまま使いたいために継承させたいです。

この文章から危惧することは、ちゃんとした継承関係(is A→基底クラス=派生クラス)が成り立っているかということです。
正しい?継承関係であれば今回のような独自のコンストラクタがあったとしてもMyBase.Newをしないということは考えにくいです。(仕様にもよりますが)
逆に呼ぶ必要が無いということからは、本当にコンストラクタとして必要なのかを考えてみてください。
一度で済むように何でも引数にすればよいというものではありません。動作するために必須のものが基本です。
クラスはその時点で設定されている状態で動作すればよいのです。あとは呼び出し側がどう設定するかだけです。
http://msdn.microsoft.com/ja-jp/library/5x4yd9d5(VS.80).aspx

引用返信 編集キー/
■23511 / inTopicNo.7)  Re[4]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ スイカ (3回)-(2008/08/17(Sun) 21:57:25)
回答どうもありがとうございます。

皆様の大変素晴らしいご意見をいただき、うれしく思っています。

残念ながら私はまだ初心者で知識の整理がついていないため、
1日ほど考えさせていただきます。
もう1〜2日したらまたこちらの方に続きを書かせていただきます。

その時はよろしくお願いします。
引用返信 編集キー/
■23512 / inTopicNo.8)  Re[5]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ オガシン (39回)-(2008/08/17(Sun) 23:12:20)
継承を行った際は、継承もとのコンストラクタから実行されます。
なので引数付きのコンストラクタのみを実装した場合、子クラスでは明示的に
親クラスのコンストラクタを呼び出さなければいけません。

なので、引数無しのコンストラクタを極力実装しましょう。
と良く言われます。

引数無しのコンストラクタが絶対に実装できないと言う状況下であれば
皆さんがいわれているようにクラス構成の考え直しが必要かもしれません。

>>Public Sub New(ByVal intValue1 As Integer, ByVal intValue2 As Integer)
MSDNの命名ガイドラインではハンガリアン記法は推奨されていません。
例えば
intValue1 ⇒ StaffNo'社員番号
intValue2 ⇒ Amount'給料
など意味の分かる変数名のほうが良いと思います。
#回答している方が引数の意味がわからないのでなんとも言えませんが等のコメントもあるので
引用返信 編集キー/
■23515 / inTopicNo.9)  Re[6]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ επιστημη (1247回)-(2008/08/18(Mon) 09:22:57)
επιστημη さんの Web サイト
> なので、引数無しのコンストラクタを極力実装しましょう。
> と良く言われます。

異議アリ。

継承したいがため"だけ"に意味の無いコンストラクタを実装してはならない!
それによって作られるインスタンスには意味が無いから。

引用返信 編集キー/
■23520 / inTopicNo.10)  Re[7]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ まどか (576回)-(2008/08/18(Mon) 11:30:24)
No23515 (επιστημη さん) に返信
>>なので、引数無しのコンストラクタを極力実装しましょう。
>>と良く言われます。
>
> 異議アリ。
>
> 継承したいがため"だけ"に意味の無いコンストラクタを実装してはならない!
> それによって作られるインスタンスには意味が無いから。

http://msdn.microsoft.com/ja-jp/library/ms229060(VS.80).aspx
ガイドラインでは「理想的には」となっていますね。

確かに作っておいたほうが無難だという言葉は聞いたことがある。
自分もリフレクションなどで既定のコンストラクタが無いと困るような場面もあるから
無意識に作っておこうという傾向は無きにしも非ず。
「それじゃぁ動作しない場合は作らない」や「設計第一」は当然のこととして。
引用返信 編集キー/
■23527 / inTopicNo.11)  Re[7]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ シャノン (576回)-(2008/08/18(Mon) 12:04:56)
No23515 (επιστημη さん) に返信
>>なので、引数無しのコンストラクタを極力実装しましょう。
>>と良く言われます。
>
> 異議アリ。
>
> 継承したいがため"だけ"に意味の無いコンストラクタを実装してはならない!
> それによって作られるインスタンスには意味が無いから。

中さんあたりに言わせるとさらに異議が出てきそう。
作られた直後のインスタンスに意味が無くとも、後で意味を注入すればよいのです、とか。

俺も「意味の無いコンストラクタは作るな」派ですがね。
ちなみに COM は「後で意味を注入」派です。
引用返信 編集キー/
■23533 / inTopicNo.12)  Re[8]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ オガシン (40回)-(2008/08/18(Mon) 13:03:02)
2008/08/18(Mon) 13:03:47 編集(投稿者)
自分で言っておいてあれですが。

>>継承したいがため"だけ"に意味の無いコンストラクタを実装してはならない!
>>それによって作られるインスタンスには意味が無いから。

俺も同意見です。
意味の無いコンストラクタから生成されたオブジェクトなんてものがあったら
それこそバグの温床になる気がします。

>>Public Sub New(ByVal intValue1 As Integer, ByVal intValue2 As Integer)
>>'処理1
>>End Sub

Public Sub New()
    intValue1
    intValue2の値を固定値として初期化処理
End Sub

こんなイメージになると思って引数無しのコンストラクタを実装してみては?
と発言しました。

処理の内容が分からないのであくまで想像ですが。

<変更>
    図表モードにしました
</変更>

引用返信 編集キー/
■23534 / inTopicNo.13)  Re[8]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ επιστημη (1250回)-(2008/08/18(Mon) 13:09:47)
επιστημη さんの Web サイト
>>継承したいがため"だけ"に意味の無いコンストラクタを実装してはならない!
>>それによって作られるインスタンスには意味が無いから。
>
> 中さんあたりに言わせるとさらに異議が出てきそう。
> 作られた直後のインスタンスに意味が無くとも、後で意味を注入すればよいのです、とか。

Creation と Initilization は別物ってスタンスなら、それはそれでよかろうと思うです。
が、できる限り Creation=Initialization にしたいと考えます、はい。
少なくとも"実装の都合"でCreationとInitializationを分けるのは避けたいなーと。

引用返信 編集キー/
■23538 / inTopicNo.14)  Re[9]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ シャノン (577回)-(2008/08/18(Mon) 14:29:08)
No23534 (επιστημη さん) に返信

> Creation と Initilization は別物ってスタンスなら、それはそれでよかろうと思うです。
> が、できる限り Creation=Initialization にしたいと考えます、はい。
> 少なくとも"実装の都合"でCreationとInitializationを分けるのは避けたいなーと。

「デザイナの都合」とか「シリアライズの都合」はどうしましょうね?
# 脱線ごめんよ。
引用返信 編集キー/
■23539 / inTopicNo.15)  Re[9]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ まどか (577回)-(2008/08/18(Mon) 14:37:18)
Public Sub New(ByVal intValue1 As Integer, ByVal intValue2 As Integer)

End Sub

#1
Public Sub New()
    Me.New(0, 0)
End Sub

#2
Public Sub New()
    _intValue1 = 0
    _intValue2 = 0
End Sub

#3
Public Sub New()
End Sub

#2と#3が意味の無いコンストラクタ?

引用返信 編集キー/
■23541 / inTopicNo.16)  Re[10]: 引数のあるコンストラクタしかもたないクラスのオーバーライド
□投稿者/ シャノン (578回)-(2008/08/18(Mon) 14:53:35)
No23539 (まどか さん) に返信

コンストラクタで生成した直後のインスタンスの状態が不正であるようなものが意味の無いコンストラクタ。
new した後で何らかの初期化メソッドを呼ばないと使えないインスタンスとか、RAII の原則に従っていないコンストラクタとか。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -