2011/10/24

いまさらVisual Basic(オブジェクト指向篇)

本日は Visual Basic のオブジェクト指向篇です。

とはいえ、今回のお話はどちらかというと Java や C++ の学習によるシナジー効果で身に付けた知識だったりします。『VB しか必要ないから VB だけがんばる』という硬直した方針では、なかなか前に進めないものだなぁと思ったり思わなかったり。

そんなわけで本日は、GoF のデザインパターンの中から個人的に気に入っているものを独断と偏見でチョイスして、実際のソースコードとともにご紹介したいと思います。



【Singleton パターン】

まずは、理解しやすく実装も容易な Singleton パターンからご紹介しましょう。

これは、プログラム内に存在するオブジェクトが 1 つだけである事を保証するための仕組みです。一体それが何の役に立つのでしょうか。その答えの一つが『ゲームプログラマになる前に覚えておきたい技術』の p.183 で述べられていますので、当該箇所を引用します。
シングルトンクラスの目的は以下のようにまとめられる。
  • 1. グローバル変数の危険さを軽減する
  • 2. グローバル変数と同じように使えるようにする
要するに、安全性を高めたグローバル変数のことである。
……だそうです。

実際には、オブジェクトを生成する際に New が実行されるたび、(新たなオブジェクトを格納するための)メモリ領域が逐一確保されます。そのため、このままでは『オブジェクトが 1 つである事』を保証できません。

Singleton クラスでは、コンストラクタを Private にする事によって、外側から New の実行を禁止します。Singleton クラスは、内部的に静的な唯一の自己参照 _instance を持ち、外部から Singleton オブジェクトを要求された場合は、その _instance を返却します。

以下に実装例を示します(展開してご覧ください)。

'  ========================================
'                 Singleton
'  ========================================


' -----------------------------------------
' Singletonクラス
Public Class Singleton

    Private Shared _instance As Singleton = New Singleton()

    ' インスタンス取得
    Public Shared ReadOnly Property Instance() As Singleton
        Get
            Return _instance
        End Get
    End Property

    Private Sub New()
        Console.WriteLine("オブジェクトを生成しました")
    End Sub

End Class

' -----------------------------------------


' テスト用モジュール
Module Module1
    Sub main()
        ' Singleton であるオブジェクトの取得
        Dim singleton1 = Singleton.Instance
        Dim singleton2 = Singleton.Instance

        If singleton1 Is singleton2 Then
            Console.WriteLine("同じオブジェクトです")
        Else
            Console.WriteLine("異なるオブジェクトです")
        End If

    End Sub
End Module

実行すると、コンストラクタが 1 回しか実行されていない事、および main 内の singleton1 と singleton2 が同じオブジェクトを共有している事が分かります。

Singleton クラスがデータを適切にカプセル化していれば、前述の通り安全なグローバル変数として使用する事ができますし、また、New が重たいオブジェクトを使い回す際にも効果的でしょう。

2011/10/23

いまさらVisual Basic(手続き指向篇)

今でこそ『MacBook がほしい』と口癖のように言っている僕ですが、実はビルゲイツとマイクロソフトに魂を売り渡しており、少年期は Visual Basic とともに過ごしておりました。

そんな事はどうでもよいのですが、このたび情報処理技術者試験も終わって気持ちに少し余裕が生まれた事ですし、原点回帰という事で、ふたたび Visual Basic を動かしてみようと思い立ったわけです。

折しも、僕の周りに『将来的に仕事で使うかも知れない』という方がいらっしゃるようなので、その方の為にもなればと簡単に VB の雰囲気をまとめてみる事にしました。


2011/10/21

Javaのよくわからない仕様

ちょっと落とし穴にはまったので備忘録。Java よりもテストコードが簡潔に書ける Processing で検証します。

まず、こちらをご覧ください。
Boolean b = Boolean.TRUE;  // TRUEで初期化した後に、
b = Boolean.FALSE;         // FALSEを代入する

なんの変哲もない、フラグの切り替えです。もちろんこれは、問題なく実行できます。

ところがこれ、List などのコレクションに集成すると、途端におかしくなる事に気付きました。

List<Boolean> boolList = new ArrayList<Boolean>();  // Booleanのリスト

  for(int i = 0; i < 10; i++) {
    boolList.add(Boolean.TRUE);     // 要素の初期化
  }

  boolList.get(0) = Boolean.FALSE;  // 代入(ここでエラー)
//~~~~~~~~~~~~~~~

これを実行すると、こんなふうに怒られちゃいます。
The left-hand side of an assignment must be a variable
えー、なんでー。

これじゃあフラグを切り替えられないじゃん!!

※ 余談ですが、『フラグをリストに格納する』というシチュエーションは、グラフアルゴリズムなどで活躍します。



実は、Boolean に限らず、コレクションの get() メソッドで取得したオブジェクトに代入しようとすると上記の現象が発生するようです。……にも拘わらず、今までこの問題を意識した事はありませんでした。

というのも、普通は、
Hoge h = hogeList.get(i);
のように、一旦 Hoge 型の変数 h にオブジェクトを代入して、h 経由でメソッドを呼んだりフィールドをいじったりできるため、『リストの特定の要素を全く別のオブジェクトで上書きしたい』という発想自体がそもそも無かったわけです。

ところが、Boolean クラスはたいへん素性の悪いもので、Java の公式ドキュメントを見ても状態を変更するメソッドが見当たりません。

そこで、スイッチしたいフラグを List#get() メソッドで取ってきて、そこへおニューのオブジェクトを代入しようという力技を思いついたのですが、まぁ前述の通りうまく行かず途方に暮れた次第であります。



【解決篇】

あれこれ悩んで Java が嫌いになりかけた頃、試しに List#set() メソッドを使ってみたら超呆気なく解決しました。なんだこれ。

List<Boolean> boolList = new ArrayList<Boolean>();  // Booleanのリスト

for(int i = 0; i < 10; i++) {
  boolList.add(Boolean.TRUE);     // 要素の初期化
}
  
boolList.set(0, Boolean.FALSE);  // 置換(これでうまくいく)

やったね。ねむい。

2011/10/18

線分の交叉判定(てきとう)

今日のテーマは、平面上における線分の交叉性を判定する計算幾何の問題です。

地味な上にそれほど大した事はない(というかつまらない)なのですが、備忘録的な意味で残しておきます。

以下の動画は、マウスで描画したストロークのうち、交叉している領域を(半リアルタイムで)見つけ出してマーキングする様子のデモです。交叉している領域は、で囲われます。



今回は、2線分の交点座標を求めず、単に交叉性のみを判定する事によって、処理を少しだけ軽くしてある辺りがチャームポイント。動画の 1 分前後からはワンストロークにおける自分自身との交叉判定も可能である事を示しています。

最適化のために頑張った割には、デモが地味すぎて悲しいので今日はこの辺で……。

2011/10/17

Processingアプリケーションでファイルのドラッグ&ドロップをサポート

秋の情報処理技術者試験も終わり、まったりと Twitter を巡回していたところ、『Processing で作成したアプリケーションウィンドウにファイルのドラッグ & ドロップ機能をサポートしたい』と考えている方を(今さらながら)発見しました。


こんにちは!Processingって、ドラッグ&ドロップを実現するコードないですよね?今後でる可能性ってあるんでしょうか… 直感的な操作を実装したい場合、D&Dは必須だと思うんです。そういう情報ってご存知ですか?2011年9月16日 10:49 via web

要するに、以下の図のように、マウスのワンジェスチャでファイルを読み込めたら便利じゃね?っていう話だと思います。


基本的には、2月7日の日記に書いた方針で実現可能なのですが、Processing の(言語的な)制約のため、当該日記のソースコードにちょっと手を加える必要があります。

2月7日の日記では、簡単のためメインクラスそのものが DropTargetListener を実装していましたが、Processing の場合はウィンドウを作成するクラス(PApplet)が隠蔽されてしまっており、(DropTargetListener に限らず)インタフェースを実装する事が事実上不可能になっているためです。

そこで、Processing 用のサンプルを超適当に作りました。早い話が手抜き更新ですが、ソースコードをコピペするだけでそれなりに動くように調整してあるのでちょっと便利です。

2011/10/16

ネットワークスペシャリストを受けてきました

本日、ネットワークスペシャリストを受けてきました。
 
準備不足を痛感させられた試験でしたが、それでも最後の最後まで力を尽くす事ができたと思います。



突然ですが…

【恐怖の午前II自己採点コーナー】

というわけで、現時点で解答が公表されている午前 II の成績を調べてみました。

合格ラインとされる正答率は 60% ですが、僕はギリギリの 64% あと 2 問不正解ならば午前で足切りされているところでした。

※ 実際の正答率は 68% でした。マークした答えをメモする際に写し間違えてしまったのでしょうか。

しかし、問題は午後 I なのです。



午後 I は、解答に全く自信がない。体感的には、たとえ部分点をかき集めても合格点に達しないのではないかというギリギリの手応え。

ネットワークスペシャリスト合格者のほとんどが及第点すれすれでパスしている事を考えると、やはり一筋縄ではいかない試験なのでしょう。

僕にとっても、これまでとは比べ物にならない難しさでした。

ですが、午後 II は意外にも 6 割を超えた自信があります。 問題文を読んだときに、『これ以外考えられない』という解答が頭に浮かぶ事が多かったです。

ですから、午後 I さえ突破できれば、合格はかなり近いのではないかと考えます。

たとえ今回落っこちたとしても、午後 I を重点的に対策して再挑戦します。まずは取り急ぎご報告まで。

2011/10/06

追悼 - Steve Jobs

2011年10月5日、Apple の元最高経営責任者 Steve Jobs が逝去した。

先日の Apple Special Event October 2011 にて iPhone 4S の発表があった直後というタイミングなだけあって、Jobs は史上最高の iPhone を見届けた上で天国へと旅立ったのだろうかと想いを馳せずにはいられない。

私は決して“信者”と呼ばれるほど Apple に傾倒していた訳ではない。 そんな私の目から見ても、彼の遺した功績はあまりにも偉大であり、今は耐え難い喪失感に打ち拉がれている。

最後に、“革新的な魔法” を私に掛けてくれた Jobs には深い哀悼と謝意を表すとともに、これからの Apple には、常に情報家電に変革をもたらし続ける存在であって欲しいと切に願うばかりである。

R.I.P.