インスタンス同士でお互いに呼び出す

解決


ペンネーム  2010-01-16 22:01:32  No: 102151  IP: [192.*.*.*]

クラスのインスタンスを複数生成して、あるインスタンスから他のインスタンスにデータの受け渡しをするなど、インスタンス同士でお互いに呼び出すことは出来ますか?または方法を教えてください。

編集 削除
特攻隊長まるるう  2010-01-17 14:01:36  No: 102152  IP: [192.*.*.*]

参照アドレスさえ持っていればどこからでも呼び出せます。

しかし、1つのインスタンスは破棄されると持っていた情報を
全て破棄しますので、全てのインスタンスの参照アドレスを
管理するのは別の存在の方が良いのです。

結局、親クラス・子クラスの関係になり、親が管理クラスと
なります。子クラスは複数のインスタンスが存在し、兄弟
を呼び出すときは直接ではなく、親クラスに呼び出すように
お願いします。

これは通常の親子クラスの設計であり、サンプルも探せば
見つかると思います。

編集 削除
ペンネーム  2010-01-17 14:40:06  No: 102153  IP: [192.*.*.*]

特攻隊長まるるうさん

ありがとうございます。
サンプルを探しているのですが、なかなかたどり着けません。
URL教えていただけませんでしょうか?
よろしくお願いします。

編集 削除
聖帝れお〜ぉハハハ。  2010-01-17 20:51:04  No: 102154  IP: [192.*.*.*]

引数の練習してからのほうがいいですよ。若葉マークがでてるし。
これ面白いよ。テトリスにも使えるじゃないかなぁ〜カナカナ。
Option Strict On
'VisualBasic2008無料製品
Public Class Form1
    Const 色_数 As Integer = 6
    Dim 色No(色_数 - 1) As Color
    Const ブロックの横幅 As Integer = 50
    Const ブロックの縦幅 As Integer = 30
    Dim r_1 As Random = New Random()


    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Me.Size = New Size(700, 700)
        Me.BackColor = Color.Gray
        With PictureBox1
            .Size = New Size(510, 500)
            .Location = New Point(20, 20)
            .BackColor = Color.Black
        End With
        Timer1.Interval = 100
        Timer1.Start()
        '色
        色No(0) = Color.Green : 色No(1) = Color.YellowGreen
        色No(2) = Color.Blue : 色No(3) = Color.SkyBlue
        色No(4) = Color.Purple : 色No(5) = Color.Pink
    End Sub
    Sub ブロック表示(ByVal g As Graphics, ByVal 表示横位置 As Integer, ByVal 表示縦位置 As Integer _
               , ByVal iro_1 As Color, ByVal iro_2 As Color)
        Dim グラデーション用変数 As Integer
        グラデーション用変数 = r_1.Next(20, 30)
        Dim グラデーション As New Drawing2D.LinearGradientBrush( _
   New Point(0, 0), New Point(グラデーション用変数, グラデーション用変数), iro_1, iro_2)
        g.FillRectangle(グラデーション, 表示横位置, 表示縦位置, ブロックの横幅, ブロックの縦幅)
    End Sub

    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        Dim g As Graphics = e.Graphics
        For ii = 0 To 2 : For i = 0 To 7
                ブロック表示(g, 20 + i * ブロックの横幅 + i * 10, 20 + ii * ブロックの縦幅 + ii * 10, 色No(ii * 2), 色No(ii * 2 + 1))
            Next : Next
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        PictureBox1.Invalidate()
    End Sub
End Class

編集 削除
ペンネーム  2010-01-20 12:26:00  No: 102155  IP: [192.*.*.*]

あのう、VB6使ってるんですが。。。
誰でもいいですから、ヒントいただけないでしょうか。
お礼はします。

編集 削除
A-S  2010-01-20 17:05:40  No: 102156  IP: [192.*.*.*]

参考になるかは解らないですけど、この辺はどうでしょうか。
求めてるものと異なっていたらすいません。

http://www.mb.ccnw.ne.jp/garger-studio/gameprog/vb0081.html

http://homepage1.nifty.com/CavalierLab/lab/vb/clsmdl/index.html

編集 削除
なな  2010-01-20 19:32:29  No: 102157  IP: [192.*.*.*]

> あるインスタンスから他のインスタンスにデータの受け渡しをする、

そのクラスに受け入れる入り口さえ作れば何でも受け渡しは可能です。
渡す側のコードについてはどこにあろうが(クラス上のコードからであろうが、標準モジュール上のコードからであろうが)関係ありません。
入り口(Publicな何か)をどうやって作るかはクラスが扱えるならご存知でしょうが、
例えば下記を書いておけば別のインスタンスを受け取れますので、
それを自身の内部のどこかに保存しておけばよろしいです。
Public sub AddInstance(clsClassInstance as Class名) '複数種を受け取りたいならas Objectとか


> インスタンス同士でお互いに呼び出す

「呼び出す」の意味がよくわかりませんが、
つまりそれぞれが相手側のインスタンスを持っていて、
相手のプロパティやメソッド等を呼び出すって事でしょうか。
それなら上記と同じです。
入り口を作ってそれぞれにインスタンスを渡せば実現します。
循環参照になりますのでインスタンスの破棄方法には十分注意して下さい。


多分ペンネームさんはクラスやインスタンスについて誤解(あるいは勉強不足)している気がします。
「クラスを動作させるとインスタンスって言う名前で呼ぶ」くらいにしか理解してないんじゃないでしょうか。

まずインスタンスとオブジェクト変数は実際には別物です。
目に見えて実際に扱っているものはインスタンスではなく、オブジェクト変数です。
インスタンスとは、クラスを元に実体化したあるひとつのオブジェクトの事です。(端的に言えばクラスの実体のひとつ)
オブジェクトとは誰かに参照される(必要とされている)事で存在意味があります。
逆に、いずれからも参照されていない(必要とされていない)なら存在理由がないとみなされ自動的に破棄されてしまいます。

通常Newキーワードで生成されたインスタンスは、そのままSetステートメントによって任意のオブジェクト変数に代入されます。
Set objInstance = New Class1
よって、この時点ではこのオブジェクト変数だけがインスタンスを参照している事になります。参照数1です。

インスタンスの明示的な破棄は、実際には直接記述できません。
実際コード上ではオブジェクト変数にNothingを代入するだけです。
Set objInstance = Nothing
Nothingキーワードは「どこでもない場所」を指すためのもので、
コード的にはこのオブジェクト変数に別の何かへの参照を代入しているに過ぎません。
しかしこれによりこのインスタンスへの参照数がひとつ減ります。
結果的に参照がゼロになったため、このインスタンスは自動的に破棄される事になります。

オブジェクト変数に入っている「参照」という値は、普通の変数と同じように代入が出来ます。
違いはSetステートメントが必要な点だけです。
つまりコピーはいくらでも作成できます。

クラスに別クラスあるいは同じクラスのインスタンスを持たせるのは、変数を持たせるのとコード上大差はありません。
ただ、「参照のひとつを消しても、すべての参照が消されない限りその実体であるインスタンスは破棄されない」というルールただそれだけが異なる点です。
よって、破棄の方法については十分検討する必要があります。
これは目に見えませんので。


以上が私のクラスに関する考え方です。
そういう目に見えない、実際に起きている現象をイメージしながら考えると、その質問内容がどこかおかしいなぁと思わざるを得ない私です。
私の考え方が間違えてるという可能性も否定できませんけど。

編集 削除
なな  2010-01-21 12:10:31  No: 102158  IP: [192.*.*.*]

> どんなお礼だろう?
「お礼はちゃんと言います(見に来ますから)」という意味だと解釈しました。
解決のチェックボックスもちゃんと押しに来るって事かなと。

そのわりに反応がなくて悲しいですけど。。。

編集 削除
特攻隊長まるるう  2010-01-22 16:58:12  No: 102159  IP: [192.*.*.*]

ヒントは既出。ボクの最初の書込みで設計が想像できないなら難しいだろうね。

[VB6.0]のコードを検索してみたけど、要点だけに絞ったものは無いですね。
ある程度の実力があれば読み解いて利用できるだろうけど、最初から自分の
考えで設計した方が良いレベルのサンプルしか引っ掛からなかったです。
いまどき、VB.NET が主流ですからね。

だから、ここで敢えてリンクを上げると A-S さんのように非常に基本的な
クラス設計の話になりますね。その後は、既に日本語で説明した通りの
設計でコードを書いてください。

ななさんの言うプロパティ経由で参照を渡すのでもいいけど、同じフォームを
複数表示して各フォーム間を自由に行き来するとなると、やっぱり親クラスで
コレクションなりに入れて一元管理する方が扱いやすいかなって思います。

.NET 版なら過去このサイトで公開してるけどね。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200606/06060011.txt
半分くらいのコードは[VB6.0]でも利用できなくも無いかw

編集 削除
ペンネーム  2010-01-23 12:08:02  No: 102160  IP: [192.*.*.*]

日立プリウスの一体型パソコンが壊れて(電源が死んで)代替機でgoogle検索でやっとここまでたどりつきました。

回答が多く寄せられていることに驚きました。
皆様ありがとうございます。

わたしの反応がないのを気にされている方もおられますので、とりあえず、たどりついたご報告をさせてていただきました。

コメント遅れて済みません。
今夜以降じっくり読ませてもらい、またコメントいたします!

編集 削除
なな  2010-01-29 08:00:21  No: 102161  IP: [192.*.*.*]

主が帰ってきたので期待あげw
…のついでにレスを。

>ななさんの言うプロパティ経由で参照を渡すのでもいいけど

意図的にはあまり違いませんが、私の提示したコード例はプロパティ経由じゃなくメソッド(公開されたSub関数)経由のものです。
一応、クラスを理解していない方が読んだとき無用な混乱をさせたくないのでレスしました。
揚げ足取りですいませんw


循環参照は持たせるべきではないってのは、本当おっしゃるとおりだと私も思います。
どうしても循環参照せざるをえないとか、そうするしか○○を実現できないというのでなければ、出来るだけ循環参照自体を避けるべきです。
ですが本人の希望もあるでしょうから望み通りの方向で提示したつもりです。

ペンネームさん、もし細かいところでわからない事があれば遠慮なく聞いてみて下さい。ばかばかしい話でも適当に答えます。
もちろん他の常連の方々のほうがよくご存知でしょうけれども、私いまとっても暇人ですので余裕ですw


以下蛇足なのですが。
私は職業プログラマーではなく素人なので考え方が相当違うと思いますが、循環参照を持たせると特に両者のイベントを検出できる点でとっても面白いコーディングが出来て楽しいですね。
自立的なプログラミングというか、それぞれのクラスが自発的に共生動作するというか・・・その仕草が自立AIみたいでとても好きです。

イベント経由で連携させるとクラスが無駄なPublicメソッドやプロパティを公開しなくてもよくなるので外から見たときすっきりしててほかのコーディングが楽だったりもします。

例えば親クラスの中に多段の入れ子になった子クラスを作りそれぞれの親子で循環参照させ、自身に起こった事やデータをイベントで伝え合うとか、中間の親はその親に子のイベントを中継したりして大元の親は直下の子のイベントだけ見ていれば他のすべての(例えば数万の)子クラスの状態を常に監視することが出来たりしてすごいことになったり。
ただイベントの発生順の考慮と、各クラスを破棄するコーディングがとにかく大変でしたw
(これもイベント経由で参照の破棄命令をやり取りさせる事でわりと簡潔なコードになりましたけど)

結局、循環参照は危険だ!という事にやっと気付いた私は参照を持たずに両者がイベントを利用するにはどうすればよいか悩み結局イベント中継クラスを設計して解決したりしました。

編集 削除
ペンネーム  2010-02-06 21:37:06  No: 102162  IP: [192.*.*.*]

>ななさん

どうしてもわかりません。
フォームモジュールまではできましたが、クラスの中身の方は全く想像もつきません。
ヒントのコードを教えてください。

Option Explicit

Dim A(100) As A
Dim i As Integer

Private Sub Command1_Click()

  For i = 1 To 100
  Set A(i) = New A
  Next i

End Sub

Private Sub Form_Unload(Cancel As Integer)

  For i = 1 To 100
  Set A(i) = Nothing
  Next i

End Sub

編集 削除
なな  2010-02-07 09:25:00  No: 102163  IP: [192.*.*.*]

>Dim A(100) As A
ここでは100という数に意味は無いのでしょうけど、
とりあえず100個の変数を作るなら宣言はDim A(99) As Aです。Forは0〜99で回してね。

でこのコードは、AというクラスがありFormモジュールのCommand1を押すと
Aのインスタンスを100個生成するコードなわけですよね。
つまり「Aというクラスを(たくさん)作る事は出来たよ!」って事ですよね。

・・・A-Sさんの提示して下さったリンク先は見ました?
その様子だとさっぱり理解出来ていないようですが、ペンネームさんはつまり
「クラスが何なのかわかっていないのにクラスを使用したいと思っている」
わけなんですよ。それはなぜですか?

>「インスタンス同士でお互いに呼び出す」
これはもちろん可能なんですが、クラスをどのように活用しようとしているのかがわからないのです。
目的が見えないからどうアドバイスしていいのかもわかんない。
そもそもタイトルの内容はいったい何の目的で行うんですか?

ペンネームさんの目的って、別にクラスを使わなければならない理由があるわけではなく
単に「クラスを覚えたい」だけなんじゃないです?
今私に出来る事は、クラスの存在意義を説明をするくらいです。


というわけで、以下クラスについての根本的な説明を書いて・・・
みようと思ったのですが時間がかかりそうなので改めて書きます。
上記でも試しながらちょっと待ってください。

編集 削除
なな  2010-02-07 10:02:06  No: 102164  IP: [192.*.*.*]

あ、配列の規定値が1から始まってるとすればコードに間違いはないみたいですね。
でも「Option Base 1」をわざわざ記述してない限り、通常は配列の最小値は0です。
(なお配列の規定値を1にするOption Base 1は混乱の元なので使用自体避けるべきです)

>Next i
・・・ん?  これって古いBasicの書き方のような気が・・・
For文のNext後方のiは省略可能です。というか書かないのが一般的ですね。
(書くなと言っているわけではないです、知識として知っておいて下さいってだけですよ)

そういえばMSDNライブラリにはこの書き方で使用例が載ってましたね。
まれにFor文を4つも5つも入れ子にする時に各NextがどのForがわかるように
あえて書いたりする事はありますけど、まぁめったに無いです。
ちなみにFor文でiを増加させているのがこのNextであるって事が明確にわかる仕様ですね。

編集 削除
なな  2010-02-07 14:16:28  No: 102165  IP: [192.*.*.*]

とりあえず提示されたコードに手を加えるとしたら、まずクラスAの中に何かパブリック変数を用意して下さい。
クラス内のPublic変数は自動的に公開プロパティとして機能しますので、例えばクラスAの先頭に
Public TestData as Long
と記述しておけば、A(i).TestDataでその変数にアクセスが出来るようになるでしょう。
クラスの外から値を入れたり出したりする事はこれだけで実現できるようになります。
やりたい事はこれだけでも実現できるかもしれませんね。

でも、クラスを作るとき通常こういったPublicな変数宣言はあまりやらないと思います。
これだけではユーザー定義型と同じ機能でしかないですよね。
であれば、そもそもユーザー定義型で事足りますから、
わざわざクラスとか言う「よくわからないもの」を使う必然性もないわけです。

繰り返しになりますが、クラスがなぜ必要なんですか?
ただのデータの入れ物が欲しいなら、クラスではなく
扱いも容易なただの変数やユーザー定義型を使うようアドバイスするところです。


おそらくクラスについての理解はまだ乏しく、
その勉強がてら何かを作ってらっしゃるんだろうと勝手に解釈しています。
というわけで、以下クラスの存在意義について実例コード付きの基本的な説明です。
ウルトラ長文です、うんざりするのを覚悟して下さいねーw


外から見たときのインスタンスの扱い方、A.Dataとか・・・どこかで見たことはありませんか?
これってユーザー定義型にそっくりじゃない?

クラスとは基本的に「処理機能を持ったデータ格納庫」です。
ユーザー定義型はまさにこの「データ格納庫」と言えます。
その点においてはユーザー定義型の宣言とクラスは存在意義がよく似ている部分があります。
ではその違いである「処理機能」とは何か?

通常クラスは自身の内部に変数を持ちます。
しかしこの変数は直接外部に公開はせず、クラス自身が利用するために宣言します。
クラスの外部からは、専用のプロパティを通じて値を出し入れ出来るようコーディングするのです。
クラスとは「ユーザー定義型に似た外観を持たせた、関数のかたまり」とも言えます。


以下クラスの機能についてユーザー定義型を用いた例で説明してみます。

例:「文字数が○○個以下の文字列を格納するデータ型を作る」

この命題を専用のユーザー定義型と専用関数で実現するものが以下のコードです。

フォームにテキストボックスを2つとボタンを1つ作り、このフォーム内に以下のコードを記述します。
────────────────────────────────────────
Option Explicit

Private Type LimitedString
    Text As String '制限文字数以下の文字を格納
    Limit As Long  '制限文字数を格納
End Type

Dim Words As LimitedString


Private Sub SetText(X As LimitedString, InputWords As String)
    X.Text = Left(InputWords, X.Limit) '制限以上の文字を切り捨てた結果を代入
End Sub

Private Sub Command1_Click()
    SetText Words, Text1.Text
    Text2.Text = Words.Text
End Sub

Private Sub Form_Load()
    Words.Limit = 10
End Sub
────────────────────────────────────────

ボタンを押せばText1を入力として文字数制限した結果がText2に表示されるというものです。
以下動作説明。

>Private Sub Form_Load()
>    Words.Limit = 10
>End Sub
フォーム起動時に、制限する文字数を10文字に設定しています。

>Private Sub Command1_Click()
>    SetText Words, Text1.Text
>    Text2.Text = Words.Text
>End Sub
テキストボックスに文字を入力してボタンをクリックすると、
その値を専用関数を介してWordsに代入しています。(専用関数SetTextについては後述)
代入処理が終わるとWords.Textの内容をText2に表示します。



まず先頭の宣言で専用のユーザー定義型変数を作っています。
>Private Type LimitedString
>    Text As String '制限文字数以下の文字を格納
>    Limit As Long  '制限文字数を格納
>End Type
>
>Dim Words as LimitedString
この変数Words.Textには文字数の制限ルールを設けたいものとします。
制限する文字数はWords.Limitの数で決まるものとします。
Words.Limitが100であれば、Words.Textには100文字までしか代入できません。
100文字以上代入しようとした場合は100文字に切り詰められるものとします。

・・・と、決めたルールですが、
ユーザー定義型には入力規制なんていう都合のいいものは備わっていません。

ルールに従うためには、このLimitedString型には直接アクセスしてはならないものとし、
代入をする際には専用の関数を通して行うようにします。
>Sub SetText (X as LimitedWords, InputWords as String)
>    X.Text = Left(InputWords, X.Limit) '制限以上の文字を切り捨てた結果を代入
>end Sub
それがこのSetText関数ですが、超過分を切り捨てて.Textへの入力を代行しています。
文字数を制限するためのフィルタのような役割をしているわけです。

一応以上でルール通りの管理が行えるようになり、ユーザー定義型と専用関数を用いて目的を達成しました。
しかし、元々このWordsは所詮ただのユーザー定義型変数です。
この変数にはいつでも直接アクセスが可能で、専用関数を介さず誤った代入をする可能性は否定し切れません。

またLimitは文字数であり、常に0以上の正数である必要がありますが、現状そのチェックはありません。
実際にはLimitの代入の際も専用関数で入力を制限する必要があることがわかります。
おまけに文字列を代入した後にLimitを変更した場合、
すでに入力された文字列と新たなLimit数の間には関連性が無くなってしまいます。
すると専用関数の数もさらに増えていく事になります。


このように、特定の変数とそれを管理する専用関数は常にセットです。
その変数は専用関数がなければ操作できませんし、逆に専用関数はその変数のためだけに存在します。
利用する側から見れば、単にユーザー定義型変数への入出力をしたいだけなのですが、
専用の関数が多くなればなるほど、その取り扱いは混乱を極めていくことになります。
この値に代入するときの関数名って何だっけ?とか、この値は直接代入してもいいんだっけ?とか。



このような場合、まさにクラスの出番と言えます。
クラスはデータと「処理機能」を同時に持つ事が出来ます。
上記のユーザー定義型変数と専用関数の両方を内部に持てるという事です。

以上と同じ実装をクラスで考えてみます。

まずclsLimitedStringクラスを作成し、以下のように記述します。
────────────────────────────────────────
Option Explicit

Private LimitedText As String '100文字以下の文字だけを格納
Private LimitCount As Long  '制限する文字数を格納

Public Property Let Text(InputWords As String)
    LimitedText = Left(InputWords, LimitCount) 'Limit数以降を切り捨てた結果を代入
End Property

Public Property Get Text() As String
    Text = LimitedText '変数の値をそのまま返すだけ
End Property

Public Property Let Limit(Count As Long)
    If Count >= 0 Then '制限文字数が0以上でなければ代入させない
        LimitCount = Count '制限文字数を代入
        Me.Text = LimitedText '現在格納している文字をもう一度代入し再チェックする
    End If
End Property

Public Property Get Limit() As Long
    Count = LimitCount '変数の値をそのまま返すだけ
End Property
────────────────────────────────────────

フォームにテキストボックスを2つとボタンを1つ作り、このフォーム内に以下のコードを記述します。
────────────────────────────────────────
Option Explicit

Dim Words As clsLimitedString

Private Sub Command1_Click()
    Words.Text = Text1.Text
    Text2.Text = Words.Text
End Sub

Private Sub Form_Load()
    Set Words = New clsLimitedString
    Words.Limit = 10
End Sub

────────────────────────────────────────


以上。
これを実行するとユーザー定義型のサンプルと同じ動作をします。

見てわかる通り、Form側のコード量が少なくなっています。
それにForm側から見るとほぼユーザー定義型と同じ使い勝手で利用できるのがわかります。
以下コードの説明。

>Private LimitedText As String '100文字以下の文字だけを格納
>Private LimitCount As Long  '制限する文字数を格納
先頭で内部変数を宣言しています。前述のサンプルでのユーザー定義型に相当するものです。
いずれもPrivateで宣言しているのは外部からアクセス不能にするためです。
(この宣言しかないクラスは外部から見ると何も見えない謎のクラスになるでしょうね)

次に、外部からデータにアクセス出来るようにプロパティを作成します。
同時に前サンプルの専用関数SetTextが行っていた制限処理をここに組み込みます。
>Public Property Let Text(InputWords As String)
>    LimitedText = Left(InputWords, LimitCount) 'Limit数以降を切り捨てた結果を代入
>End Property
普段「Sub」か「Function」の2種類を使って関数という名のコードの集まり(ステートメント)
を書いていると思いますが、プロパティでは「Property」という単語で宣言します。
SubとFunctionの書き方が良く似ているように、Propertyもそっくりで簡単です。

この時点で、このクラスはプロパティとしてTextという名前が見えるようになります。
しかし代入は出来ますが、参照は出来ない状態です。
Words.Text = "hoge"
は可能ですが、
Text2.Text = Words.Text
のほうはエラーで実行できないという事です。まさに片手落ちですね。
プロパティの宣言で書いた「Property Let」は代入の処理を記述するためのものです。
参照の処理を記述するにはこれとは別にもうひとつ「Property Get」を記述する必要があります。
>Public Property Get Text as String
>    Text = Words.Text '変数の値をそのまま返すだけ
>end Sub
ここで、出力用のプロパティを宣言します。
関数で言えば戻り値にWords.Textを渡しているのと等しい処理内容になっています。

さらにLimitCountについても入出力するためにLimitプロパティを作成しています。
>Public Property Let Limit(Count As Long)
>Public Property Get Limit() As Long
ここには、前サンプルには無かった制限文字数のチェック
>    If Count >= 0 Then '制限文字数が0以上でなければ代入させない
>        LimitCount = Count '制限文字数を代入
>    End If
と、既存文字列に対して新制限文字数の適用をリアルタイムに行う処理
>        Me.Text = LimitedText '現在格納している文字をもう一度代入し再チェックする
を加えてあります。


このように、クラスはユーザー定義型の能力と+関数の能力という2つの能力を持ったものです。
使うときは変数と同じように振る舞い、しかしその中身はいずれも関数みたいなものなんですね。
「変数であり関数である」という2つの側面を持つとも言えます。

「データの集まり」+「処理機能」ですよと言った意味、これでわかったかなぁ。

クラスを使用すると、それを利用する場面でとてもコーディングが楽になるわけです。
可読性も向上しますし、書いてて混乱する事もも少なくなります。

しかし逆に、ユーザー定義型の宣言のように数行で簡単に済ますことが出来なくなりますし、
NewしたりNothingを入れたりと管理の手間も多少増えます。
そもそもユーザー定義型に比べ処理コストが大幅に多くなります。(処理時間や消費メモリが増加します)
なによりクラス自体の設計は結構大変です。
クラスのコーディング途中はわりと混乱しがちです。(私のクラス設計が悪いのかもしれませんが)



で、話は戻ってクラスを使う目的はなんですか?

使おうと思えば、クラスは取るに足らない用途にも使えます。
使えますがコーディングが大変になるだけですよ。
VB6では1クラス1モジュールなので管理モジュール数も無駄に増えます。
クラスをクラスとしてちゃんと活かせないなら、使っても良い事なんて本当にありません。
それだけは覚えておいて下さい。
(正直、例のサンプルもしょうもない使い方の一つと言えます)



以下蛇足です。
ここまではユーザー定義型を引き合いに出して話しましたけど、もうひとつ
クラスに良く似た使い方が出来る身近な存在があるんですが、わかります?
それはフォームやコントロールです。

様々なプロパティがあって代入が出来たり参照が出来たりするメンバーを持っている。
フォームはクラスに非常に良く似てますよね。というかうりふたつです。
それもそのはずでフォームもクラスの一種なんですよ。(扱いがやや特殊ですけど)
フォームとクラスの根本的な違いは、表示機能を持っているか持っていないかの違いだけです。
GUIを持っている関係上フォームのほうは特別扱いされてはいますが、
目に見えるというその点をのぞけば、その扱い方はクラスと同一なんです。

Propertyステートメントだってクラスモジュールでしか使えないものと思われがちですが、
実はフォームモジュールにもプロパティを記述できちゃうんですよ。
独自のプロパティやメソッドを持ったフォームだって作れるわけですね。

フォームがクラスに似た存在である事を簡単に確かめるためには、
新規コマンドボタンに以下のコードを記述して実行してみて下さい。
────────────────────────────────────────
>    Dim objForm As Form1
>    Set objForm = New Form1
>    objForm.Caption = Me.Caption & "のコピー"
>    objForm.Visible = True
────────────────────────────────────────
すると、Form1と全く同じフォームがもうひとつ出現します。
フォームのインスタンスを作ると、もうひとつフォームが出来るという例です。
ボタンを何度も押せばいくつでも、そしてどのフォームのボタンからも新しいフォームが出来ます。

これは実行中のフォームというのは、実はそれぞれがインスタンスのひとつである事を意味し、
逆説的にフォームモジュールとはクラスモジュールと同等の扱い方が出来ることを意味します。

これらの新しいフォームは元のとそっくりですが、別のインスタンスなので内部変数も別物です。
よって、前述のようなサンプルのフォームでは各テキストの内容とかもちゃんと正常に動作します。
(※いずれのサンプルも変数をフォーム内部に持たせているためそういう動作をします)

New Form1という書き方はクラスの記述法とは異なりますが、
NewをSetすることで新たなインスタンスが出来上がっているのは同様ですね。
クラスと大きく異なる点は、スタートアップのフォームは自動的にNewされVisibleがTrueになる事と、
その参照はVBがこっそり保持しているという事、
フォームが消滅していてもアクセスされるとまた自動的にNewされる事くらいです。
あとこの変数にNothingを入れてもフォームは消えないし、終了しないという特殊な点にも注意してください。
このフォームを呼び出し元で消そうと思ったら
>Unload objForm
と記述します。普段フォームを終了させる時はUnload Meと記述していると思いますが、
このUnloadステートメントが行っているのはVBが保有しているフォームインスタンスの破棄だったわけです。
(ちなみにUnloadした後でもこのobjFormにアクセスすると上記のルールのとおりで
  勝手に再度Newされてしまう危険があります。Unloadを呼んだらさっさとNothingをSetしましょう)


このフォームの話はほんと完全なる蛇足ですから忘れてもらって構いません。
正直クラスの本質がわからないと何言ってるのかわかんないと思いますし。
クラスが理解できれば、この辺の今まで理解できなかった(理解する必要もなかった)
特別な存在についても実はそんなに特別ではなくクラスと同じ考えで把握出来ますよという例です。

と、ここまで書くのに4時間かかっちゃったw
以上暇ななでした。

編集 削除
長い  2010-02-07 22:36:20  No: 102166  IP: [192.*.*.*]

長文ご苦労様ですけど、もう少し簡潔に説明できた方が
いいと思います。
主観とか除けばかなりわかりやすい説明だと思います。

編集 削除
ペンネーム  2010-02-07 23:05:56  No: 102167  IP: [192.*.*.*]

>ななさん

とても詳しい説明本当にありがとう!
いただいたコードをもとに実際やってみますね。
とりあえず見てますって報告させていただきました。
また近いうちにコメントさせてもらいます^^
もうすこし時間ください。

編集 削除
かいけつ  2010-02-22 19:09:15  No: 102168  IP: [192.*.*.*]

かいけつですね。

編集 削除
ペンネーム  2010-02-28 23:57:09  No: 102169  IP: [192.*.*.*]

解決してないです。

編集 削除