親子関係を持つ自作クラスのDownCast

このQ&Aのポイント
  • .NET2.0ベースのVBで親子関係を持つ自作クラスのDownCastについて解説します。
  • ビルド時にCType部分でエラーが発生し、「変換演算子によって、ある型からその派生型に変換することはできません」とメッセージが表示されます。
  • このアプローチが間違っているのか、なぜダウンキャストが不可能なのか、詳しく説明します。
回答を見る
  • ベストアンサー

親子関係を持つ自作クラスのDownCast

.NET2.0ベースのVBです。次のコードをビルドしようとすると、CTypeの部分がエラーとなり、「変換演算子によって、ある型からその派生型に変換することはできません」とメッセージがでます。派生クラスに対して、ある一定の法則でダウンキャストさせたいのですが、なぜ不可能なのでしょうか。また、このようなアプローチは間違っているでしょうか。 Public Class Class1  ' このクラスは別ファイルに定義されており、  ' そのファイルは ReadOnly。  Public foo  Public bar  Public baz End Class Partial Class Class1  ' 継承クラスで実装すると、クラス階層構造がより一層複雑になるので、Partial として実装。  ' ダウンキャスト用にキャスト演算をオーバーロード  Public Shared Narrowing Operator CType(ByVal value As Class1) As Class2   Dim result As New Class2   ' .foo は移さない!   result.bar = value.bar   result.baz = value.baz   Return result  End Operator End Class Public Class Class2 : Inherits Class1  Public hoge End Class

質問者が選んだベストアンサー

  • ベストアンサー
  • MARU4812
  • ベストアンサー率43% (196/452)
回答No.1

エラーとなる理由はエラーメッセージでMSDNを見れば書いてあります。 継承クラス間の定義は宣言した時点で実装済みです。 しかし、 そもそも、ダウンキャストの概念自体が危険であり、それ自体を避けるべきです。 継承元が継承先に依存するので、クラス設計としても問題ありでしょう。 また、実質、VB.NET の継承ではダウンキャストは出来ないと思います。 継承は関係なくなり、特定のクラスから特定のクラスへキャストすると いう意味になり、メンバ間の引継ぎが実装できないのでしょう。 ※継承している時点でアップキャストはできます。 どうしても実装したいというのであれば、ダウンキャスト用の独自関数を 作って下さい。 また、その他の指摘事項として、 Partial を使っているが質問の趣旨と関係あるような意味は無いはずです。

sumire_kanou
質問者

お礼

ありがとうございます。

関連するQ&A

  • 自作クラスのイベントを外部ハンドラでスレッドセーフ

    ■.NETモジュールプロジェクト(DLL) Public Class MyClass   Public Event hoge( ByVal sender As Object, ByVal e As EventArgs )   Private WithEvents Timer As Timers.Timer   Private Sub New()     Timer = New Timers.Timer : Timer.Interval = 10 : Timer.Start()   End Sub   Private Sub fuga( ByVal sender As Object, ByVal e As EventArgs ) Handles Timer.Elapsed     RaiseEvent hoge( Me, New EventArgs ) ' 一定時間ごとにイベントを発生させる   End Sub End Class ■上の.NETモジュールを参照している Windows Form アプリケーションプロジェクト(EXE) Public Class Form1   Private WithEvents foo As MyClass.MyClass   Public Sub New()     InitializeComponent()     foo = New MyClass.MyClass   End Sub   Private Sub bar() Handles foo.hoge     TextBox1.Text = "baz" ' TextBox1 は デザイナで Form1 に貼り付け済み   End Sub End Class という 2 プロジェクトを含むソリューションを作成しました。実行すると、 有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'TextBox1' がアクセスされました。 というエラーが出てきます。 foo が MyClass ではなく、system.windows.forms.dll などに入っている Button や Form といったコントロールの場合は、上記の bar() のような書き方でもスレッドセーフに扱えるので、MyClass もForm1 のコードを修正する事なく、利用できたらなと思っています。 その場合、どのように MyClass を書けばいいでしょうか。環境は VS2008 で、.NET2.0 ベースです。

  • C++で継承元のクラスの代入演算子を呼び出す方法

    C++であるクラス継承したクラスの代入演算子で 継承元のクラスの代入演算子を呼び出す方法がわかりません。 こんな感じのソースです。 class T { T& operator=(const T &t) { } } class U :: T{ U& operator=(const U &u) { // ここでT.operator=()の代入演算を実行したい } } ((T)(*this)).operator=((T)(u))のようにキャストすればいけるかと思ったんですが、 コンパイルエラーでした。 よろしくお願いします。 また、これはプログラム上好ましくない手法でしたら、 別な実現方法をお教えください。

  • (jQuery)同じクラス名のオブジェクトを一斉操

    jQueryで同じクラス名のオブジェクトを一斉操作するにはどうしたら良いでしょうか? 【したいこと】 3つのチェックボックスのいずれかにチェックを入れると disabledである「お問合わせ」と「お申込み」ボタンがクリックできるようにしたいです。 1つでもチェックが入っていなければボタンはdisabledにしたいです。 【現状】 3つのチェックボックスの1番上のclass="foo"のみクリックすると動作します。 ▼【 HTML 】 <input type="checkbox" class="foo"> <input type="checkbox" class="foo"> <input type="checkbox" class="foo"> <input type="submit" class="bar" value="お問合わせ"> <input type="submit" class="bar" value="お申込み"> ▼【 jQuery 】 // アクセス時はボタンは無効にする。 $(document).ready(function(){   $('.bar').attr('disabled', true); }); // チェックボックスクリックアクション $('.foo').click(function() {   $('.bar').each(function() {     if($('.foo').prop('checked') == true) {       $('.bar').attr('disabled', false);     } else {       $('.bar').attr('disabled', true);     }   }); }); ご教授の程どうぞ宜しくお願い致しますm(__)m

  • matchを使用してCSSのクラスがあるか知りたい

    例えばHTML内に書かれているclassを取得して fooのクラスがあるときのみalertを出したい場合、 ※<div class="hoge foo bar">のようなclassを取得 if(cls.match("/foo/")){ alert("fooがあります。"); } ・・・このように書くとclass="hoge fool bar"の時でも trueになってしまいます。 matchで正規表現を使用して判定したい場合、 どのように書けばよいのでしょうか?

  • 派生クラスから基本クラスprotectedメンバへのアクセスについて

    C++初心者です。 以下のような基本クラスcoordと、その派生クラスquadがあり、quadクラスに関して=演算子をオーバーロードしました。 class coord { protected: int x, y; }; class quad : public coord { public: quad operator=(coord &ob2); }; quad quad::operator=(coord &ob2) { x = ob2.x; y = ob2.y; } するとob2からxにアクセスできないとエラーが出ます。 quadクラスのメンバ関数内なので、基本クラスのprotectedメンバにはアクセスできると思ったのですが、違うのでしょうか。 ご教授お願いします。

  • クラスの初期値設定について

    早速ですが、教えてください(開発環境は WindowsXP,VisualBasic.NET2003 です) Public Class CCC Private Key As Integer Private Value As String End Class 上記のようなクラスを用意して Public Sub SSS() Dim III() As CCC = New CCC() {{1, "VALUE1"}, _ {2, "VALUE2"}} End Sub といった具合に初期値を設定したいのですが、 コンパイルエラー(配列初期化子の次元が多すぎます。)に なってしまいます。(ほかに思いついた記述パターンも試してみましたがだめでした) 仕方なく、CCCに下記のようなメソッドを作って Public Class CCC Private Key As Integer Private Value As String Public Sub SetValue(ByVal a As Integer, ByVal b As String) Key = a Value = b End Sub End Class このメソッドを利用し Public Sub SSS() Dim III() As CCC III(0).SetValue(1, "VALUE1") III(1).SetValue(2, "VALUE2") End Sub 上記のように初期値を設定するようにしています。 初期化子({})をつかって、C言語?風に初期値を設定することは できないのでしょうか? 上記の例では、顕著に現れてませんが、クラスの中のクラスにも 初期値を設定しようとする場合、どのような初期値が設定されて いるかが、ソース上、整然と並ばなくなってしまい、修正しにくい 、見た目が美しくない状態になってしまいます。 何かよい方法はないのでしょうか?ご教示願います。 (参考URLだけでもかまいません、よろしくお願いします)

  • VB6構造体をVB2008クラスで行う場合

    何方かの質問「VB6構造体をVB2008クラスで行う場合」 の回答プログラムにて参考とさせて頂きましたが 申し訳ありません、初心者しにて・・・・・教えてください。 値を「登録、参照部分」のクラス(抜粋) Public Class Program   Public Shared Sub Main()    (省略)   End Sub End Class 上記部分なのですが (1)Sharedを使用する訳はなんでしょうか?(省いても問題ありませんか?) (2)登録、参照部分のクラスPublic Shared Sub Main()を「登録のメソッド」と「参照のメソッド」に   分けたいのですがどうしてもうまくいきません。   何方か御教授願えないでしょうか? よろしくお願いします。 「以下何方かの質問の回答プログラム」 ■クラス+コレクションクラス Public Class Group   Public MainID As Integer   Public SubID As Integer   Public Value1 As Integer   Public Value2 As Integer End Class Public Class GroupCollection : Inherits System.Collections.Generic.Dictionary(Of Integer, Group)   Public Shadows Sub Add(ByVal Item As Group)     MyBase.Add(Item.SubID, Item)   End Sub End Class Public Class Program   Public Shared Sub Main()     Dim DataDict As New GroupCollection     Dim NewGroup As New Group     NewGroup.MainID = 1     NewGroup.SubID = 101     NewGroup.Value1 = 123     NewGroup.Value2 = 234     DataDict.Add(NewGroup)     Console.WriteLine(DataDict.Item(101).Value2) ' 出力 234   End Sub End Class

  • 浮動小数点数の誤差

    恐ろしく基本的なこと聞きます。 Public Class himajin100000 Shared Sub Main Dim foo As Double = 0.5 '2進数で表現できる Dim bar As Double = 0.1 '割り切れないから誤差が出る System.Diagnostics.Trace.WriteLine((foo - bar).ToString) '0.4 '・・・あれ?浮動小数点数の誤差どこ行った? End Sub End Class

  • 【ASP.NET】 独自で作成したクラスが認識されない

    お世話になります。ASP.NETに関する質問です。 Visual Studio 2008の開発環境において、 画面右側のソリューションエクスプローラより 右クリックして[新しい項目の追加]をクリックして 新規にクラスファイル(Class1.vb)の作成(言語: Visual Basic)を 行いました。 別のソースファイルより、上記で作成したクラスをインスタンス化 しようとしたところ、コンパイル時に下記エラーが出力されます。 ------------------------------------------------------ 型 'Class1' が定義されていません。 ------------------------------------------------------ クラスをインスタンス化しているソースの記述は以下の通りです。 (test.vb)--------------------------------------------- '変数宣言 Dim cl1 as Class1 = Session.Contents("クラス1") ------------------------------------------------------ Class1.vbの内容は以下の通りです。 (Class1.vb)------------------------------------------- Public Class Class1 Protected _LoginTime As String Public Property LoginTime() As String Get Return _LoginTime End Get Set(ByVal Value As String) _LoginTime = Value End Set End Property End Class ------------------------------------------------------ どなたか原因と対処方法についてご教授願えますでしょうか? 以上、よろしくお願いいたします。

  • 親クラスの初期化についてご教授ください

    javaの勉強を始めた者です。質問させてください。 以下のようなコードの、 親クラスの初期化をしている部分の挙動が、 うまく理解できません。 class p{ public int i = 3; public void foo(){}; } class c extends p{ public int i = 0; public void foo(){ System.out.print("foo "); } } public class b{ public static void main(String[] s){ p bar = new c(); // ←ここです bar.foo(); System.out.print(bar.i); } } 実行結果は「foo 3」です。 以下の点が理解できません。 ・なぜメソッドは子クラスのものが実行されるのに、プロパティは親クラスのものが表示されるのか? ・子クラスのコンストラクタを利用することで、いったいどのような挙動となるのか? オブジェクト指向の基礎を理解しれません・・・よろしくお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう