2011年9月16日金曜日

→→→抽象クラスより難しい「インタフェース」

インタフェースは、抽象クラスと同じように、機能の大枠を定めるもの

Module Module
  Sub Main()
    Dim c As New Class1()
    c.Output()
  End Sub
End Module


Interface Interface1
   Sub Output()
End Interface


Class Class1
  Implements Interface1


  Public Sub Output()
    Implements Interface1.Output


    Dim s As String = "こんにちは"
    Console.WriteLine(S)
  End Sub
End Class

Interface1インタフェースを実装したClass1
Implementsキーワードを使い、Interface1の実装であることを示す

インタフェースは、抽象クラスよりも厳しい制約を課すものと言える。
抽象クラスClass1の中に記述していた文字列変数sの宣言はInterface1に書くことはできない。
インタフェースはメンバー変数を持てない。
Class1のメンバー変数として文字列sを記述することもできない。
インタフェースを実装するクラスは、メンバー変数を勝手に追加することができない

→→→そのまま使えない「抽象クラス」

そのまま使えない、必ず子クラスを作って追加実装をしなければいけない「抽象クラス(abstract class)」というものがある。
Module Module1
  Sub Main()
    Dim c As New Class2()
    c.Output()
  End Sub
End Module


MustInherit Class Class1
    Protected S As String = "こんにちは"
    Public MustOverride Sub  Output()
End Class


Class Class2
    Inherits Class1
    Public Overrides Sub Output()
         Console.WriteLine(S)
    End Sub
End Class


Class1クラスは抽象クラス。MustInherit(継承しなければいけない)と記述しているし、OutputメソッドはMustOverride(オーバーライドしなければいけない)と書かれた抽象メソッドで、中身の記述がない。
Class2クラスではOutputメソッドをオーバーライドして処理を記述している。Class1ではOutputメソッドの外側を記述し、Class2で内側を記述しているようなもの。
Class2の段階まで持っていけばインスタンス化して利用できる。
Class1は直接はインスタンス化して利用できない。Class2をClass1に書き換えるとエラー。

抽象クラスは「何をするか」の大枠だけを決めておいて「どのようにするか」を子クラスにまかせる仕組み

→→→メソッドのオーバーライド

メソッドのオーバーライド(override)という機能。簡単に言えば子クラスで親クラスのメソッドを「上書き」する機能。

Module Module1
  Sub Main()
    Dim c As New Class2()
    c.Output()
  End Sub
End Module


Class Class1
   Protected S As String = "こんにちは"
   Public Overridable Sub Output()
     Console.WriteLine(S)
   End Sub
End Class


Class Class2
   Inherits Class1


   Public Overrides Sub Output()
     Console.Write(S)
     Console.WriteLine(S)
   End Sub
End Class

Class2のインスタンスcを作り、そのOutputメソッドを呼び出す。Class2クラスのOutputメソッドが呼び出される。ここでは「こんにちは こんにちは」と表示される
Class2の親であるClass1にもOutputメソッドがあるがOverridableと書いてオーバーライドを許可している。Class2クラスではOverridesと書いてオーバーライドすることを示している。
Class2の外部からClass1のOutputを呼び出すことはできない。
でも、Class2の内部からであれば、
MyBase.Output()
と記述することによって、親クラスのOutputメソッドを呼び出せる。

2011年9月15日木曜日

→→→継承

クラスには「継承(inheritance)」という機能がある。

Module Module1
 Sub Main()
   Dim c As New Class2()
   c.Output()
   c.Output2()
 End Sub
End Module

Class Class1
  Protected S As String = "こんにちは"
  Public Overridable Sub Output()
    Console.WriteLine(S)
  End Sub
End Class


Class Class2
  Inherits Class1


  Public Sub  Output2()
     Console.Write(S)
     Console.WriteLine(S)
  End Sub
End Class

Class2クラスのインスタンスcを作り、そのOutputメソッド、Output2メソッドを呼ぶ。
でも、Class2クラスを見ると、Outputメソッドはない。
また、Output2メソッドの中で参照しているSもない。
それらはClass1から継承されている。
継承を行う場合には、Inheritsキーワードを使って継承元を指定する

→→→メソッドのオーバーロード

現在のVisula Basic や C# では同じ名前を持つメソッドを複数作れる。
それをオーバーロード(overload)という。

Module Module1
  Sub Main()
    Dim c As New Class1()
    c.Output()
    c.Output("こんばんは")
  End Sub
End Module

Class Class1
  Private S As String = "こんにちは"
  Public Sub Output()
     Console.WriteLine(S)
  End Sub

  Public Sub Output( s As String )
     Console.WriteLine(s)
  End Sub
End Class

パラメータなしのOutput
文字列のパラメータを一つ持つOutput
が記述されている
呼び出し元の形で使い分ける
別のオーバーロードとするためには、パラメータの個数と型が一致しないようにする。
Newコンストラクタも、オーバーロードを利用できる。
例えば、「Sub New()」と「Sub New(s as String)」を並存させることが可能。

→→→インスタンス生成時に呼び出される「コンストラクタ」

インスタンス生成時に呼び出されるコンストラクタは、インスタンスの初期化を行うのに便利。
●Newコンストラクタの利用例
Module Module1
   Sub Main()
      Dim c As New Class1()
      c.S = "こんにちは"
      c.Output()
   End Sub
End Module

Class Class1
   Public S As String
   Public Sub New()
     Console.WriteLine("コンストラクタが呼ばれた")
   End Sub
   Public Sub Output()
     Console.WriteLine(S)
   End Sub
End Class


●Newコンストラクタにパラメータを持たせた利用例
Module Module1
   Sub Main()
      Dim c As New Class1("こんにちは")
      c.Output()
   End Sub
End Module

Class Class1
   Public S As String
   Public Sub New(s As String)
     Me.S = s
   End Sub
   Public Sub Output()
     Console.WriteLine(S)
   End Sub
End Class