SSブログ

「オブジェクト指向プログラミング」について(その2) [プログラミング]

http://himakou.blog.so-net.ne.jp/2012-08-21 の続き

助手: 博士,前回は「オブジェクト指向プログラミング」を次のように踏み込んで定義しましたが,もう少し具体的に教えてもらえませんか。

「オブジェクト指向プログラミング」とは,全体的な手続きの「流れ」を重視してきた従来のプログラミングと異なり,処理の「オブジェクト(=対象物)」を重視することによって,「オブジェクト」に固有の手続きに関するプログラミングを全体的な手続きの「流れ」から分離することを目指すことで,プログラム全体の見通しをよくするプログラミング「手法」である。

博士: よしよし。それではVisual Basic 2008(以下「VB」)を用いて,具体的にプログラムを書き分けてみようかの。たとえVBが不慣れであっても,プログラムを比較することで,「オブジェクト指向プログラミング」の雰囲気を味わってもらいたい。

助手: よろしくお願いします。博士: お題は「小さい方から100000番目の素数を見つけ出すプログラム」じゃ。キミならどう書くかな?

助手: とりあえずこんな感じでいかがでしょうか。IsNotPrime(i)はBoolean型の配列であり,iが素数でない場合にTrueとなるようなエラトステネスのふるいを意味します。答えは「1299709」と出ました。

<例1>
    Sub Main()
        Dim t As Double = Timer
        Dim x As Integer = 100000
        Dim nmax As Integer = 100000000
        '**
        Dim IsNotPrime(nmax) As Boolean
        IsNotPrime(0) = True
        IsNotPrime(1) = True
        Dim i As Integer
        For i = 2 To nmax
            If Not IsNotPrime(i) Then
                Dim j As Integer = 2
                Do While i * j <= nmax
                    IsNotPrime(i * j) = True
                    j += 1
                Loop
            End If
        Next
        '**
        Dim counter As Integer = 0
        For i = 0 To nmax
            If Not IsNotPrime(i) Then
                counter += 1
                If x = counter Then
                    Debug.Print("{0}", Timer - t)
                    MsgBox(x & "番目の素数は" & i & "です")
                    Exit Sub
                End If
            End If
        Next
        Debug.Print("{0}", Timer - t)
        MsgBox(x & "番目の素数は" & nmax & "よりも大きいです")
    End Sub


博士: 有名なエラトステネスのふるいじゃな。小さい方から順に発見した素数の倍数をつぶしていくというものだが,必要なふるいのサイズがnmax = 100000000で十分と決めつけているのには目をつぶるとしても,これは全体的な手続きの「流れ」を重視したプログラミングの典型例と言えよう。

助手: 全体的な手続きの「流れ」を重視したプログラミングが何かいけないんでしょうか。

博士: いけないとまでは言っとらん。ただし,「オブジェクト指向プログラミング」的なセンスでこう書くこともできる。

<例2>
    Sub Main()
        Dim t As Double = Timer
        Dim x As Integer = 100000
        '**
        Dim PrimeNumber As New List(Of Integer)
        Dim counter As Integer = 0
        Dim i As Integer = 2
        Do
            Dim IsNotPrime As Boolean = False
            Dim j As Integer
            For Each j In PrimeNumber
                If (i \ j) * j = i Then
                    IsNotPrime = True
                    Exit For
                End If
            Next
            If Not IsNotPrime Then
                PrimeNumber.Add(i)
                counter += 1
                If x = counter Then
                    Debug.Print("{0}", Timer - t)
                    MsgBox(x & "番目の素数は" & i & "です")
                    Exit Sub
                End If
            End If
            i += 1
        Loop
    End Sub


助手: なるほど。素数のリストを徐々に増やしていくやり方ですね。

博士: 「オブジェクト指向プログラミング」的なセンスを取り入れたことが伝わるかのう。どういうことかというと,素数のリストを重要な「オブジェクト」と捉え,これをList(Of Integer)クラスのPrimeNumberというインスタンス(=変数)で表現したのじゃ。ListクラスはMicrosoftによって提供されており,後から要素を追加していくことができる便利なクラスである。はじめは空っぽだったPrimeNumberインスタンスに発見した素数を追加していくことで素数のリストを育てていくイメージじゃ。

助手: PrimeNumber.Add(i)という部分で実際に素数を追加しているわけですね。それにしても,素数のリストをFor Each文で使うあたりがオシャレですねえ。

博士: (得意げに)そうじゃろそうじゃろ。とはいえ,Listクラスという強力なクラスを使うことさえ思いつけば,「オブジェクト指向プログラミング」などと大きく出る話ではない。

助手: そうすると,「オブジェクト指向プログラミング」にはまだ先があると?

博士: そうじゃ。<例2>をさらに「オブジェクト指向プログラミング」的に書き直すとこうもできる。

<例3>
    Sub Main()
        Dim t As Double = Timer
        Dim x As Integer = 100000
        '**
        Dim p As New PrimeNumber
        Dim i As Integer
        For i = 1 To x
            p.AddNextPrime()
        Next
        Debug.Print("{0}", Timer - t)
        MsgBox(x & "番目の素数は" & p(x - 1) & "です")
    End Sub

    Public Class PrimeNumber : Inherits List(Of Integer)
        Public Sub AddNextPrime()
            If Me.Count = 0 Then
                Me.Add(2)
                Exit Sub
            End If
            Dim i As Integer = Me.Last() + 1
            Do
                Dim IsNotPrime As Boolean = False
                Dim j As Integer
                For Each j In Me
                    If (i \ j) * j = i Then
                        IsNotPrime = True
                        Exit For
                    End If
                Next
                If Not IsNotPrime Then
                    Me.Add(i)
                    Exit Sub
                End If
                i += 1
            Loop
        End Sub
    End Class


助手: 基本的なロジックは変わっていないようですが,ClassとかInheritsとか見慣れないキーワードが出てきますねえ。

博士: Public Class PrimeNumber : Inherits List(Of Integer)の意味は,List(Of Integer)クラスを継承するPrimeNumberクラスを自ら定義するということじゃ。PrimeNumberクラスには,AddNextPrimeというメソッドが定義されているが,このメソッドのおかげで全体的な手続きの「流れ」が

    Sub Main()
        Dim t As Double = Timer
        Dim x As Integer = 100000
        '**
        Dim p As New PrimeNumber
        Dim i As Integer
        For i = 1 To x
            p.AddNextPrime()
        Next
        Debug.Print("{0}", Timer - t)
        MsgBox(x & "番目の素数は" & p(x - 1) & "です")
    End Sub


と,非常に直感的な形に書けている点が「オブジェクト指向プログラミング」の最大の恩恵じゃ。これならVBがわからなくても,全体的な手続きの「流れ」が一目瞭然ではないかな?

助手: 確かにおっしゃるとおりです。これならPrimeNumberクラスの定義をよく読まなくても,PrimeNumberクラスのpインスタンスに対して,p.AddNextPrime()で素数をポチポチ追加している雰囲気がよくわかります。かといって,PrimeNumberクラスの定義も決してわかりづらいわけではなく,全体としてプログラムが読みやすくなった気がします。

博士: そのとおりじゃ。素数リストという「オブジェクト」をPrimeNumberクラスとしてキャラ立ちさせ,エラトステネスのふるいに素数を追加するという固有の手続きをPrimeNumberクラスのAddNextPrimeメソッドとして切り出すことで,全体的な手続きの「流れ」の見通しがよくなったということじゃな。

助手: 恐れ入りました。。(その3に続く)
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。