- 締切済み
インターフェース型の使い方がわかりません。
ライブラリにあるメソッドはcopy()で コピー処理があるクラスに飛んで、コピーして戻ってくるのはわかりますが、 インターフェース型の使い方がさっぱりわかりません。 簡単にインターフェース型とはどういうものか教えてください。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- あんらいぷ ぜろいち(@Unripe01)
- ベストアンサー率84% (11/13)
ご指摘の通り、.Copy()でした。 あまりいい例ではないんですけど、無理矢理インターフェース型を作るとこんなかんじですかねぇ。。。 メソッドをインターフェース型にするというよりも、 インターフェースを継承しているクラスを、インターフェース型にキャスト無しで代入できると考えたほうがいいのでは? で、その代入されたインターフェースのメソッドを実行すると、継承先で実装されたクラスの関数を実行できますよと。 インターフェースを継承するクラスの中の実装は何でもいいよ。 そのかわり、必ず同じ名前のメソッドを実装してね。 ってなもんでしょうか・・・ううん。短くていいコードが書けないですが、これで何となくでも参考になればいいかと。 Module Module1 Sub Main() 'インターフェース型に格納 Dim sampA As New SampleClassA sampA.SampleStrA = "値を入れたよ" Dim Isca1 As ICopy = sampA Dim Isca2 As ICopy = New SampleClassB '動きを確認するために、ちょっと冗長な宣言 'CopyメソッドはSampleClassAクラスを返すので、SampleClassB型には入れれない。 Dim A As SampleClassA = Isca1.Copy() Dim B As SampleClassA = Isca2.Copy() Console.WriteLine(A.SampleStrA) Console.WriteLine(B.SampleStrA) End Sub End Module Public Class SampleClassA Implements ICopy Public SampleStrA As String 'コピーメソッド Public Function Copy() As SampleClassA Implements ICopy.Copy Dim CopyClass As New SampleClassA CopyClass.SampleStrA = "" '基本、文字は空白で返します Return CopyClass End Function End Class Public Class SampleClassB Implements ICopy Public SampleStrB As String 'コピーメソッド Public Function Copy() As SampleClassA Implements ICopy.Copy Dim CopyClass As New SampleClassA CopyClass.SampleStrA = "必ずあたいが入っているクラスを返します" Return CopyClass End Function End Class 'インターフェース Public Interface ICopy Function Copy() As SampleClassA End Interface
- あんらいぷ ぜろいち(@Unripe01)
- ベストアンサー率84% (11/13)
すいません、説明が抽象すぎたようです。 「クラスを丸ごとコピー」についてですが、試しに コンソールアプリケーションを作成して、以下のコードを実行してみて下さい。 Module Module1 Sub Main() Dim sca1 As New SampleClassA sca1.SampleStrA = "これはsca1の文字列です" 'sca1 のメッセージ表示 Console.WriteLine(sca1.SampleStrA) 'sca2sca1を代入して、SampleStrAの中身を換えてみる Dim sca2 As SampleClassA sca2 = sca1 sca2.SampleStrA = "これはsca2の文字列です" 'sca1とsca2 のメッセージ表示 Console.WriteLine("----sca1とsca2 のメッセージ表示----") Console.WriteLine(sca1.SampleStrA) Console.WriteLine(sca2.SampleStrA) 'Copyメソッドを使ってメッセー表示 Dim sca3 As SampleClassA = sca1 sca3.SampleStrA = "これはsca3です" Console.WriteLine(sca3.SampleStrA) End Sub End Module Class SampleClassA Public SampleStrA As String 'コピーメソッド Public Function Copy() As SampleClassA Dim CopyClass As New SampleClassA CopyClass.SampleStrA = SampleStrA Return CopyClass End Function End Class 期待値としては、 これはsca1の文字列です これはsca2の文字列です と出てほしいのですが、どちらも「これはsca2の文字列です」と出ると思います。 こういう動きは望ましくないので、通常はICopyインターフェイスを実装して、Copy() 関数を作るようにします。 で、クラスの代入の時に sca2 = sca1.Copy() とやってあげれば、別々の文字列が出力できるでしょう。(sca3です) rescue100さんの認識である >自分が作ったクラスのコピーする関数をICopy()インターフェースに集めることができるってことですか? >この認識で合っていますか? については、「集める」という表現が漠然としていますが、 多分大丈夫だと思います。 もう少し厳密にすると、集めるというよりは、ICopyインターフェースを実装すると、Copy()メソッドを必ず実装しなければならないので、 (ああ、コピーできるんだな)って分かる ってだけの話なんです。 極論ですが、 別にICopyインターフェイスなんて実装しなくてもいいのです。今回の上記サンプルには、ICopyインターフェースは実装してません。 ただCopyメソッドがあるだけです。別にKOPI()メソッドでもいいんです。 でも、.NET開発の世間一般のお決まりとして、 「クラスのコピーはCopy()メソッドという名前にしようね」という取り決めがあるので、「このクラスは、コピーできる機能があるから、この関数の名前をCopyにしよう。ああ、そうだCopyインターフェースをつけておけば、他の人が使う時にCopyできるよという目印になるな」 ってなもんで、インターフェースを実装するのです。 だから最初のうちは、インターフェースを実装していると書かれていれば、そういう名前の場合は共通としてお決まりの動きが決められている と覚えておけばいいと思います。 たまにこんがらがるとすれば、 インターフェースという言葉は別の意味でも使われるので、 上の説明内容であるインターフェースと、別物だと認識できればパニックにならないと思います。 例えば ファイルインターフェース そのファイルがどのような内容が書かれているか 等。
お礼
ありがとうございます。 実行してみました。 コンソール出力を先にしているから、この場合うまくいってるだけのような・・・ 'Copyメソッドを使ってメッセー表示 Dim sca3 As SampleClassA = sca1 sca3.SampleStrA = "これはsca3です" Console.WriteLine(sca3.SampleStrA) ↑ Dim sca3 As SampleClassA = sca1.copy では??? んーなるほど。 オブジェクト名.メソッド名で、メソッドを呼び出すことが出来るのですね。 いままで、call 関数名()使ってました・・・ このようにメソッドはわかるんですけど、Copy()をICopyインターフェース型にして作ることはできません。 インターフェース型にコピーや貼り付けなどを集めるところまでは理解できたのですが・・・
クラスを扱う時に、外側からあたかも別の型のように扱う事ができるように定義するのがインタフェースです。複数の別のクラスに同じ性質を持たせ、統一的に扱いたい時に便利です。 例) クラス A と クラス B が共通のインタフェース II 型を持っていると、クラス A と クラス B を、インタフェース II 型として、For Each などで取り扱う事ができます。 Option Strict On Public Class Form1 Private Interface II Function Say() As String End Interface Private Class A Implements II Public Function Say() As String Implements II.Say Return "Yes" End Function End Class Private Class B Implements II Public Function Say() As String Implements II.Say Return "No" End Function End Class Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim objs As II() = New II() {New A(), New B()} For Each obj As II In objs MsgBox(obj.Say()) Next End Sub End Class 上記例では、インタフェース型の配列 objs を定義していますが、 Dim objs As II() = New II() {New A(), New B()} 配列要素の実体はクラス A とクラス B です。 しかし、あくまでインタフェース型として扱うので、インタフェース型の Say メソッドを For Each で共通的に呼び出す事ができます。 クラス A と クラス B がインタフェース型を持っていない場合には、次のようなコードになるでしょう。 Option Strict On Public Class Form2 Private Class A Public Function Say() As String Return "Yes" End Function End Class Private Class B Public Function Say() As String Return "No" End Function End Class Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim objs As Object() = New Object() {New A(), New B()} For Each obj As Object In objs If TypeOf obj Is A Then MsgBox(DirectCast(obj, A).Say()) 'あくまでクラス A として扱う ElseIf TypeOf obj Is B Then MsgBox(DirectCast(obj, B).Say()) 'あくまでクラス B として扱う End If Next End Sub End Class
お礼
ありがとうございます。 >クラスを扱う時に、外側からあたかも別の型のように扱う事ができるように定義するのがインタフェースです。 私には同じ型に統一しているように見えます。 >Dim objs As II() = New II() {New A(), New B()} この書き方は、Implementsしているクラス同士でないと記載できないのですか? >MsgBox(obj.Say()) YESNOって表示されますか? Handles MyBase.Loadでエラーが出て、デバッグできませんでした。 MsgBox(obj.Say())になにが入るかデバッグモードでVS2005だとどうやればいいのですか? 昔、値に何が入っているか見ながらデバッグやった記憶があります。 トレースモードもやってみましたがなにも表示されない・・・
- あんらいぷ ぜろいち(@Unripe01)
- ベストアンサー率84% (11/13)
はじめまして。 参照URL貼っておきました。 インターフェイスって、「お約束の名前」だと思えば大丈夫! 例えば携帯電話だと、どの機種にもメニューボタンがあって、数字のボタンがあって、電源ボタンがあって、、、 って必ず決まってますよね。 メニューボタンを押すと、メニュー画面が開きますし、 数字のボタンを押せば数字が画面に表示されて、 電源ボタンは、ちょっとだけ押したら作業がキャンセルされるし、長押ししたら電源が切れます。 これって、機種を買い換える毎にいちいち説明書を見なくてもなんとなく機能が予想できると思います。 ただ、機種によってちょっとだけ動きが違っていて、電源ボタン長しても、「処理をキャンセルしますか?」なんて親切に確認画面がでてくる機種もあるし、いきなり待ち受け画面に飛ばされて残念な気持ちになったりしますよね。 ぱっと見ただけで、なんとなく処理が理解できるような仕組み。 これが「インターフェイスの実装」です。 つまり、「Copyインターフェイスを実装している」と表記されていると、(ああ、このクラスは値のCopyができるんだな。)って分かってよね? ってことです。(もちろん中の処理はちょっと違いますが。) 先ほど、インターフェースを使った事がない と言ったのは、 一人でプログラムを組んでいる限り、インターフェースが必要になることは殆どないからです。 なぜなら、自分がプログラムを理解していたらそれで事足りるから。 でも、100人とかで一つのプログラムを組んでいたら、クラスの中身を丸ごとコピーするような関数(メソッド)を作って! とみんなに伝えても、ある人はClone()って名前をつけたり、Copy()って名前を付けたり、もしかしたらkopi()とか、hukusei()なんてつける人もいるかもしれないです。 これだと、後々何がなんだかわからなくなるので、 「絶対にCopy()という名前」で、クラスの中身をコピーする処理を書いてほしいわけです。 インターフェースの機能として、自分で作ったクラス内に、インターフェースを宣言すると(厳密には継承といわれてる?)、インターフェースに実装されている関数名を必ず使わなければコンパイルが通らないようになります。 この機能を利用して、100人全員にICopyインターフェースを宣言してね!って伝えておけば、嫌がおうにもCopy()関数を実装しないとだめなので、統一感が出ますよね。 Copy()関数なのに、文字列に変換するような処理が書かれるともうお手上げですけど^^A なかなか理解しずらいインターフェイスですが、 今は気にしないでいいと思いますよ!
お礼
ありがとうございます。 クラスの中身を丸ごとコピーするってなんですか・・・ インターフェース型は実装される関数名を必ず使わなければならない。なるほど。 自分が作ったクラスのコピーする関数をICopy()インターフェースに集めることができるってことですか? この認識で合っていますか?
お礼
ありがとうございます! 夏でPCが壊れました・・・返事が遅れてすみませんでした!!