システムメンテナンスのお知らせ

ライブラリにあるメソッドはcopy()で

コピー処理があるクラスに飛んで、コピーして戻ってくるのはわかりますが、

インターフェース型の使い方がさっぱりわかりません。

簡単にインターフェース型とはどういうものか教えてください。

gooドクター

A 回答 (4件)

ご指摘の通り、.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
    • good
    • 0
この回答へのお礼

ありがとうございます!

夏でPCが壊れました・・・返事が遅れてすみませんでした!!

お礼日時:2009/07/15 15: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できるよという目印になるな」

ってなもんで、インターフェースを実装するのです。

だから最初のうちは、インターフェースを実装していると書かれていれば、そういう名前の場合は共通としてお決まりの動きが決められている
と覚えておけばいいと思います。

たまにこんがらがるとすれば、
インターフェースという言葉は別の意味でも使われるので、
上の説明内容であるインターフェースと、別物だと認識できればパニックにならないと思います。

例えば
ファイルインターフェース
そのファイルがどのような内容が書かれているか 等。
    • good
    • 0
この回答へのお礼

ありがとうございます。

実行してみました。
コンソール出力を先にしているから、この場合うまくいってるだけのような・・・

'Copyメソッドを使ってメッセー表示
Dim sca3 As SampleClassA = sca1
sca3.SampleStrA = "これはsca3です"
Console.WriteLine(sca3.SampleStrA)


Dim sca3 As SampleClassA = sca1.copy では???


んーなるほど。
オブジェクト名.メソッド名で、メソッドを呼び出すことが出来るのですね。
いままで、call 関数名()使ってました・・・


このようにメソッドはわかるんですけど、Copy()をICopyインターフェース型にして作ることはできません。

インターフェース型にコピーや貼り付けなどを集めるところまでは理解できたのですが・・・

お礼日時:2009/07/07 15:34

クラスを扱う時に、外側からあたかも別の型のように扱う事ができるように定義するのがインタフェースです。

複数の別のクラスに同じ性質を持たせ、統一的に扱いたい時に便利です。

例)
クラス 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
    • good
    • 0
この回答へのお礼

ありがとうございます。

>クラスを扱う時に、外側からあたかも別の型のように扱う事ができるように定義するのがインタフェースです。

私には同じ型に統一しているように見えます。

>Dim objs As II() = New II() {New A(), New B()}

この書き方は、Implementsしているクラス同士でないと記載できないのですか?

>MsgBox(obj.Say())

YESNOって表示されますか?


Handles MyBase.Loadでエラーが出て、デバッグできませんでした。

MsgBox(obj.Say())になにが入るかデバッグモードでVS2005だとどうやればいいのですか?
昔、値に何が入っているか見ながらデバッグやった記憶があります。
トレースモードもやってみましたがなにも表示されない・・・

お礼日時:2009/07/02 19:33

はじめまして。


参照URL貼っておきました。

インターフェイスって、「お約束の名前」だと思えば大丈夫!
例えば携帯電話だと、どの機種にもメニューボタンがあって、数字のボタンがあって、電源ボタンがあって、、、
って必ず決まってますよね。

メニューボタンを押すと、メニュー画面が開きますし、
数字のボタンを押せば数字が画面に表示されて、
電源ボタンは、ちょっとだけ押したら作業がキャンセルされるし、長押ししたら電源が切れます。

これって、機種を買い換える毎にいちいち説明書を見なくてもなんとなく機能が予想できると思います。
ただ、機種によってちょっとだけ動きが違っていて、電源ボタン長しても、「処理をキャンセルしますか?」なんて親切に確認画面がでてくる機種もあるし、いきなり待ち受け画面に飛ばされて残念な気持ちになったりしますよね。

ぱっと見ただけで、なんとなく処理が理解できるような仕組み。
これが「インターフェイスの実装」です。

つまり、「Copyインターフェイスを実装している」と表記されていると、(ああ、このクラスは値のCopyができるんだな。)って分かってよね?
ってことです。(もちろん中の処理はちょっと違いますが。)

先ほど、インターフェースを使った事がない と言ったのは、
一人でプログラムを組んでいる限り、インターフェースが必要になることは殆どないからです。
なぜなら、自分がプログラムを理解していたらそれで事足りるから。

でも、100人とかで一つのプログラムを組んでいたら、クラスの中身を丸ごとコピーするような関数(メソッド)を作って!
とみんなに伝えても、ある人はClone()って名前をつけたり、Copy()って名前を付けたり、もしかしたらkopi()とか、hukusei()なんてつける人もいるかもしれないです。

これだと、後々何がなんだかわからなくなるので、
「絶対にCopy()という名前」で、クラスの中身をコピーする処理を書いてほしいわけです。
インターフェースの機能として、自分で作ったクラス内に、インターフェースを宣言すると(厳密には継承といわれてる?)、インターフェースに実装されている関数名を必ず使わなければコンパイルが通らないようになります。

この機能を利用して、100人全員にICopyインターフェースを宣言してね!って伝えておけば、嫌がおうにもCopy()関数を実装しないとだめなので、統一感が出ますよね。
Copy()関数なのに、文字列に変換するような処理が書かれるともうお手上げですけど^^A

なかなか理解しずらいインターフェイスですが、
今は気にしないでいいと思いますよ!

参考URL:http://www.atmarkit.co.jp/fdotnet/basics/oop07/o …
    • good
    • 0
この回答へのお礼

ありがとうございます。

クラスの中身を丸ごとコピーするってなんですか・・・

インターフェース型は実装される関数名を必ず使わなければならない。なるほど。

自分が作ったクラスのコピーする関数をICopy()インターフェースに集めることができるってことですか?
この認識で合っていますか?

お礼日時:2009/07/02 18:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング