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

→→→静的メンバー(共有メンバー)

インスタンス化なしでクラスの機能を使うためには、Sharedを追加して、共有メンバーする。

Module Module1
  Sub Main()
     Class1.S = "こんにちは"
     Class1.Output()
  End Sub
End Module

Class Class1
   Public Shared S As String
   Public Shared Sub Output()
     Console.WriteLine(S)
   End Sub
End Class

→→→クラス

クラス(Class)はオブジェクト指向プログラミングの中心となる要素である。クラスにはメンバー変数とメソッドを格納できる。
メンバー変数にはデータを入れることができ、メソッドは処理を記述したものを入れる
データと処理が一つになっているのがポイント。

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 Output()
        console.WriteLine(S)
    End Sub
End Class

Class1がClass1クラスで、文字列型のメソッド変数S、Outputメソッドである。

起動時に呼び出されるMainプロシジャでは
Dim c As New Class1()
でClass1クラスのインスタンスを作り、それを「c」という名前で参照できるようにしている。
ここは、
Dim c As Class1 = New Class1()
と書くこともできる。

c.sでcのsに「こんにちは」を代入している。cのOutputメソッドを呼び出すと「こんにちは」が出力される。
クラスは「インスタンス化」してから使うのが基本である。インスタンスは日本語では「実体」。インスタンスを「オブジェクト」と呼ぶこともある。

クラスのメンバーには、アクセス修飾子を用いることができる。赤文字のPublicが、Publicはクラスの外部からこのメンバーへのアクセスを許可する。「Private」と指定すると、外部からアクセスできなくなる。

一つのクラスから複数のインスタンスを生成できる。
Sub Main()
  Dim c As New Class1()
  c.S = "こんにちは"
  c.Output()


  Dim d As New Class1()
  d.S = "こんばんは"
  d.Output()
End Sub
Class1クラスのインスタンスを二つ生成し、それぞれを「c」「d」という名前で参照している。



→→→値の読み書きが処理につながる「プロパティ」

Propertyの例

Module  Module1
 Dim MessageValue As String
 Property Message As String
     Get
           console.WriteLine("MessageがGetされました")
           Return MessageValue
     End Get
     Set(value As String)
           MessageValue  =  value
           Console.WriteLine("MessageがSetされました。値は「" & value &"」です")
     End Set
 End Property

 Sub Main()
     Message = "こんにちは!"
     Console.WriteLine(Message)
 End Sub
End Module


Messageという名前の文字列型プロパティがあり、その裏側で値を保持するMessageValue変数を用意している。
MessageValue変数をMessageプロパティを通じて利用する。
コード⇔Messageプロパティ⇔MessageValue変数

MessageプロパティはGetプロシジャとSetプロシジヤを持っている。Message値が読み出されたときにはGetプロシジャが呼び出され、書き込まれた時にはSetプロシジャが、呼び出される。

利用する側からは、プロパティは変数と同様に見える。

トランザクション ログの肥大化

SQL Server 2008 R2ではデフォルトでは、トランザクションログは、ハードディスクの空き領域がなくなるまで、またはファイルサイズが最大になるまで、どんどん肥大化していく。

ログの肥大化を防止するには、ログを定期的にバックアップするしかない。

バックアップを実行すると、トランザクションログの使用済み領域を切り捨てることができる。
ログのバックアップにより使用済み領域を解放して、空き領域へ変換してくれるので、その領域が再利用できるようになる。

しかし、ログの切り捨ては、再利用可能な領域を作るだけで、ファイルサイズを縮小するわけではない。
しかし、大きく肥大化したファイルの場合は縮小したい場合がある。
この場合は DBCC SHRINKFILE コマンドを実行する

DBCC SHRINKFILE(論理名, 縮小後のサイズ)

1.まずログの使用量を確認。
DBCC SQLPERF(LOGSPACE) コマンドを使用してLog Size/Log Space Usedを見てみる。

2.FORMATオプションでバックアップを実行。
BACKUP DATABASE ***DB
 TO DISK = 'C:\***DB.bak' 
   WITH FORMAT

3.ログ バックアップの実行
BACKUP LOG ***DB
 TO DISK = C:\log1.bak'

4.DBCC SHRINKFILE(log1) を実行

でログファイルは縮小される。

2011年9月14日水曜日

→→→整数には下限と上限がある


整数型の変数には、値の上限と下限がある。どんな数字をいれてもよいわけではない。
Dim i As Integer = Integer.MaxValue
MsgBox(i)
MsgBox(i + 1)
整数型変数iに整数型の上限値を入れて初期化。出力は21億4748万3647が整数の上限値である。
このiに1を加えたものを出力はできない。OverflowExceptinが生じる
整数値は、マイナス21億4748万3648~21億4748万3647の値を格納できる。それ以外の値を格納しようとするとオーバーフローとなる。
この範囲が狭い場合は、正の数だけでよいから上限を大きくしたい場合は符号なし整数型であるUIntegerを使えばゼロ~42億9496万7295の値まで格納できる。長整数型(Long)を使うのもいい。
Integerが4バイトであるのに対してLongは8バイトでマイナス922京3372兆368億5477万5808~922京3372兆368億5477万5807までを格納できる。符号なしの長整数型であるULongはゼロ~1844京6744兆737億955万1615を格納できる

2011年9月12日月曜日

→→→ToStringメソッド/Parseメソッド

数値から文字列に変換する処理は、自動的に行われることも少なくはないが、ただ、自動ではうまくいかないときもある。その一つの例は
Dim i As Integer = 1
MsgBox("iは" + i )
「iは1」というダイアログを出してくれそうに思えるが実際はエラーメッセージが出て停止してしまう。
文字列「iは」をDouble型に変換しようとして、InvalidCastExceptionが生じてしまう。
解決策は
MsgBox("iは" + i.ToString())
とすることである。数値を文字列に変換する方法はいくつかあるが、ここではInt32構造体のToStringメソッドを使って、iが格納する数値を文字列型な変換している。現在のVisualBasicとC#では、基本的なデータ型であっても、色々なメソッドを呼び出せるようになっている。文字列に変換するToStringメソッドは、多くの構造体クラスが持っている。Visual Basicの場合、+演算子を変更してエラーを回避することもできる。
MsgBox("iは" & i )
とすればよい。+演算子は加算と文字列連結の両方に用いられるので、文字列連結をはっきり示すには&演算子を使うほうがいい。

数値を文字列に変換するとは逆に、文字列を数値に変換する時に使えるのがParseメソッド
Dim s As String = "123"
Dim t As String = "456"
MsgBox( s + t )
MsgBox(Integer.Parse(s) + Integer.Parse(t))
最初のメッセージでは「123」「456」を連結して「123456」と出力するが、
次のメッセージでは123を数値にしたものと456を数値にしたものを足し合わせ「579」を出力する。
Int32のParseメソッドは4種類のオーバーロードを持っているので、他にも多くの構造体やクラスが文字列からデータを受け取るParseメソッドを備えている。

→→→文字列を格納する文字列型

String型:Visual BasicやC#の文字列型は可変長で、最大で約20億(2の31乗)個のUnicode文字を格納できる。ただ実際に20億個の文字を格納すると約4Gバイトのメモリーを使ってしまうので、実用上の限度はもっと下にあると考える。
Visual Basic やC#の内部の文字コードセットはUnicodeである。ただファイルに保存したり通信をする際には文字コードセットとエンコーディングに注意する必要がある。
<シフトJISのsjis.txt、UTF-8のutf8.txt、UFT-16のutf19.txtを作るコード>
  Dim path As String = "C:\test\"
  Dim s As String = "ABC123ABC123あいう"

  System.IO.File.WriteAllText(path & "sjis.txt", s , System.Text.Encoding.GetEncoding("Shift_JIS"))
  System.IO.File.WriteAllText(path & "utf8.txt", s ,System.Text.Encoding.UTF8)
  System.IO.File.WriteAllText(path & "utf16.txt", s ,System.Text.Encoding.Unicode)

文字列型変数の既定値は、何も入っていない文字列("")ではなく、Nothing(どこにも関連付けられていない) であることに注意が必要である。
 Dim s As String = ""
と初期化して使うべき時もある。