2004-12-21
目次
SqueakではじめるSmalltalk入門 第23回 鷲見正人
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回はメソッドの再定義、つまりオーバーライドです。
a StockAccountもa BankAccount同様、「balance」あるいは「balance: …」というメッセージを受けとることができます。ただ、a BankAccountのときとその振る舞いは異なります。つまり“多態”するわけです。
a StockAccountにとって、「balance」というメッセージを受けて返すべき値は、インスタンス変数balanceの値【註1】ではなく、新しく設けられたインスタンス変数pricePerShareとnumSharesの積でなけければいけません。同様に、メッセージ「balance: …」に対しては、pricePerShareの単価で購入できるぶんの株数をnumSharesに設定すること、がそれに相応しい振る舞いとなります。なお、ここでは簡単のため、株数に端数も許すことにしています。
balance
^ self pricePerShare * self numShares
balance: aNumber
self numShares: aNumber asFloat / self pricePerShare
メッセージasFloatは、主に整数(an Integer)などに対して送信することで等価の浮動小数点数(a Float)を返します。これは、Integer >> #/ がan Integerをパラメータに取るとき、分数(a Fraction)を生成してしまうので、こうした状況を防ぐための処置です。参考まで、次にInteger >> #/の定義を転載しておきます。【註2】
Integer >> / aNumber
| quoRem |
aNumber isInteger ifTrue:
[quoRem _ self digitDiv: aNumber abs neg: self negative ~~
aNumber negative.
(quoRem at: 2) = 0
ifTrue: [^ (quoRem at: 1) normalize]
ifFalse: [^ (Fraction numerator: self denominator: aNumber)
reduced]].
^ aNumber adaptToInteger: self andSend: #/
さて、実はこれでStockAccountの定義は完了です。そう、#deposit:と#withdraw:は再定義の必要はないのです。論より証拠。実際に試してみることにしましょう。
| stock |
World findATranscript: nil. "transcriptを開く"
stock _ StockAccount new. "a StockAccount作成"
stock balance: 300. "300円預金"
Transcript cr; show: stock balance. "残高照会 => 300.0 "
Transcript cr; show: stock numShares. "株数に換算 => 10.0 "
stock deposit: 90. "90円預入"
Transcript cr; show: stock balance. "残高照会 => 390.0 "
Transcript cr; show: stock numShares. "株数に換算 => 13.0 "
stock withdraw: 240. "240円払戻"
Transcript cr; show: stock balance. "残高照会 => 150.0 "
Transcript cr; show: stock numShares. "株数に換算 => 5.0 "
stock withdraw: 180. "180円払戻"
Transcript cr; show: stock balance. "残高照会 => 0.0 "
Transcript cr; show: stock numShares. "株数に換算 => 0.0 "
なぜこのようなことになるのかについては、次回、解説します。
註1:サブクラスには、スーパークラスのメソッドだけでなく、そこで定義されたインスタンス変数も継承されるので、a StockAccountには本来無用なインスタンス変数balanceも継承されてしまっています。継承させる属性を取捨選択するための言語機能が備えられていないことは、Smalltalkでクラス指向、つまり「C++タイプのオブジェクト指向」をすることが難しいことを意味します。純粋なクラス指向で考えたとき、あれもない、これもない状態のSmalltalkは、かなり駄目なオブジェクト指向言語なのです。
註2:メソッドのメッセージパターンには、本来不要な「クラス名 >> 」という表現を追記して、そのメソッドがどのクラスに帰属するのかを明示的にすることがあります。以降の回ではサンプルメソッドにもこのような表記を用いることがあるので、もし、ブラウザなどにコピー&ペーストしてそのまま使用するときは、「クラス名 >> 」の部分は選択せずに、それを省いた残りをコピーするようにしてください。
バックナンバー:
http://squab.no-ip.com:8080/mosaren/
藤本裕之のプログラミング夜話 #59
再度承前。カッコの話の続きである。前回はカッコというモノが「その内包する部分をその外側から隔離して評価するという意味の表現」である、という結論を出して終わった。今回はこのシカツメらしい定義の意味するところ、カッコの存在意義の根源に筆を進めて行きたい。
こんな話からはじめてみよう。カッコを多用することで一部に熱狂的排斥論者を持つLISPという言語がある。この言語の入門用によく出される課題に「animal」というタイトルの……まぁゲームと言ってよければゲーム、データベースと呼べばデータベースのプログラムを作る、というのがある。
要はユーザーが頭に描いているanimal、すなわち動物をプログラムが当てるというものだ。LISPのコードをここに書いてもタイクツするヒトが大過労から……この誤変換面白いね、多かろうから、どういう構造かを散文的に解説する。御用とお急ぎでない方は、以下のURLで完成品の(英語だけど)ソースが手に入るのでご鑑賞くだされ。
http://cvs.sourceforge.net/viewcvs.py/*checkout*/clocc/clocc/src/cllib/animals.lisp
まず最初に一つの質問と二つの答えを用意する。例えば「その動物はクビが長いですか?」と質問し、ユーザーの「はい」あるいは「いいえ」という答えを待つ。ユーザーが「はい」と答えれば「その動物はキリンですか?」、「いいえ」なら「その動物はゾウですか?」と確認する。
この確認にユーザーが「はい」と答えればセッションは終了、答えが「いいえ」の場合、プログラムは降参し、ユーザーにその動物の名前を入力してもらう。そして、たとえばそれが「フラミンゴ」だったとすると(なるほどフラミンゴだってオレやあなたよりは首が長い)プログラムはこう要求する。「キリンとフラミンゴを区別するための質問をひとつ教えてください」。
そして次にこのプログラムが起動されたときは最初とは動作が変わっている。まず「その動物はクビが長いですか?」は同じだが、「はい」と答えると、さっきユーザーに教えてもらった次の質問を聞いてくるわけ。「その動物には羽がありますか?」とかね。
ユーザーが誠実にこのプログラムの相手をすれば、プログラムは多くの動物に関する知識を集積することになる。
このプログラムの根幹にあるロジックは単なる二分法である。全ての動物という集合を、とりあえずは「クビが長い動物とそれ以外」に分け、そのそれぞれのなかをまた入れ子のごとく「これこれこういうモノとそれ以外」で二分していくわけだ。
諸星大二郎「孔子暗黒伝」の読者ならご存知のように、これはつまり中国古代、易経に観られる世界観である。まず最初に混沌とか太極とかいう一個の存在があり、これが陰陽(両儀という)に分かれる。そのそれぞれがまたニつに分かれて四象、また別れて八卦……これがあの「当るも八卦、当らぬも八卦」の八卦ですな。
さて、この細分と統合に使われる便法がすなわちカッコである。万物は集合でありカッコはその部分集合を定義する道具、すなわち世界を分割する道具である。そして部分集合としてその外部から切り離される以上、その内側には切り離された妥当な理由が存在する。首が長いとか、胎生であるとか、染色体のペアがXYであるとか、全国共通学力試験における偏差値が60以下であるとか、いろいろね。
こういう分割を我々は通常「分類」と言っている。
そしてこれらの分類は全て(中には許しがたく差別的なものもあるが機能的には、ということね)、この混沌とした世界を「整理し理解しようとするココロミ」なのである。カッコが多いのは言い換えれば事態が執拗に分析されまくった証拠でもあるのであり(もちろん間違った分析である場合もあるが「執拗に」おこなわれたことに変わりはない)、プログラマたるものがそれを見て怖気をフルったりしてはいけないのである。
(2004_12_16)
高橋真人の「プログラミング指南」第58回
〜Perlについて(4)〜
こんにちは、高橋真人です。
さて、前回の配列とリストとは別のものだというお話をしましたが、Cを使っている方は、「そんなことは当たり前だろ」と思われるかもしれません。
int array[] = {5, 26, 32, 79, 100};
というコードがあった場合、代入の左辺であるarrayと右辺である{5, 26, 32, 79, 100}との関係で見れば、当然右辺のようなものを配列とは呼ばないでしょうからね。
ところが、Perlを使い慣れてくると、リストと配列を同じ感覚で使えるケースが殊の外多いことに気づくのです。たとえば、
$a = 10;
$b = 20;
$c = 30;
@array = ($a, $b, $c);
といったように、変数をカンマで区切ってからカッコで囲んでもリストになりますし、さらには、リストを左辺に置くこともできてしまうのです。例えば以下のような感じです。
($a, $b, $c) = @array;
この場合、@arrayの保持している要素が、先頭から順に$a、$b、$cに代入されていきます。@arrayの要素数が3より多い場合には先頭の3個のみが代入され、3個よりも少ない場合には代入される値のないものにはundefという特殊な値が入ります。
また、リストの特定の要素を[]で指定することもできます。
$value = (5, 23, 7)[1];
ここでは、$valueには23が入ります。さらに、Perlでは配列の末尾要素を-1で指定できますが、リストにおいても可能です。
$value = (5, 23, 7)[-1];
$valueには、リストの末尾要素である7が入るわけです。
さらに、リストを返す演算子を利用すれば例えば「ファイルパスの末尾から2番目の要素を取り出す」なんてことも簡単にできます。
$path = 'Macintosh HD:Users:mosa:Desktop:file.txt';
$desktop = (split /:/, $path)[-2];
これで、$desktopには’Desktop’が入ります。splitという演算子は、
split DELIMITER, STRING
という構文で使われる演算子で、文字列STRINGをDELIMITERで区切り、区切られた各要素をリストにして返すようになっています。
ちなみに、DELIMITERの部分は「正規表現」という特殊な表記法を使いますが、これについてはまた機会を改めて説明します。
このように、Perlしか知らない人にとっては、意外にリストと配列の区別というのは付きにくいものなのです。
しかし、以上のような例を見ることで、かえってC/C++系の言語のベテランには納得がピンと来る方が多いのではないでしょうか。
例えばCでも配列を返す関数に対してインデックス参照をすることが可能です。
char array[256];
char c;
c = strcpy(array, "Hello")[1];
strcpy()は、第2引数を第1引数にコピーするのが第一義的な目的なので、第1引数のポインタを返すことは普段あまり意識しませんが、このように書けば、ちゃんと文字列として機能するので[1]というインデックス参照によって2番目の要素を返すので、変数cには’e'が入るわけです。
C++を使うようになると特に、この手の「一時的に作られて、すぐになくなる値」というものの存在を意識することが多くなりますが、結局これらの値は変数として存在するものではないので読み出し以外の操作はできません。
同様に、Perlのリストも要素を操作する(つまり、読み出すだけではなく何らかの変更処理を伴う)演算子(関数)を適用することはできないのです。
なので、
@array = sort (5, 2, 9, 1);
は、OKですが、
@array = shift (5, 2, 9, 1);
はエラーです。
sort演算子は、引数を変更することなく、引数と同じ要素をソートされた形で返しますが、shift演算子は、先頭要素を返すと同時に引数のリストの第1要素を削除する仕組みになっているからです。
ニュース・解説
今週の解説担当:小池邦人
【開発環境】
Mac OS X 10.3.6の登場から1ヶ月ちょっとしか経っていませんが、早くも次のMac OS X 10.3.7が登場しました。ビデオカードのドライバ更新(バグ取り?)がメインの仕事のようです。Mac OS X 10.3.6で生んでしまったバグや積み残したバグの退治も行われているようです。今回のビデオカードのドライバの改良は、ゲームアプリケーションでの画面表示スピードの改善などには随分と効果があるようです。ところが、うちのNvidia GeForce 68000 GT DDLの表示速度をXBenchで測定してみると、以前に搭載してたビデオカード(何だっけ… ATI Radeon 9600 XTかな?)よりも悪いスコアのままで、10.3.6からあまり変化はありません(涙)。まあ、ベンチマークアプリの癖もありますので断言はできませんが(自作アプリでは高速だなと思う時もあるので…)、まだまだビデオカードの潜在能力を100%引き出すほどドライバがチューニングされていないのかもしれません?Tigerに期待したいと思います。
Dashboard Widgetsの2回目のコンテストが開始されたようです。一回目ではあまり面白いWidgetsが集まらなかったのでしょうか(笑)。Tigerのプレビュー版でWidgetsを開発するためのSDKや解説資料は、ADCメンバーサイトにアップロードされています。また後述する「Tiger Developer Overview Series: Developing Dashboard Widgets」も大いに参考になるでしょう。賞品のiPodを狙ってみてください(バスケ君に続け!)
http://developer.apple.com/macosx/tiger/dashboard/index.html?headlines
【テクニカルドキュメント】
前回から12月17日の期間中、Apple社のDocumentationサイトには新規ドキュメントがひとつも登録されませんでした。その代わり、Release Noteサイトには2つのドキュメントが追加されています。「AppleEvent Manager」は、Mac OS X 10.3でAppleEvent Managerに加えられた変更点が解説されています(結構重要)。またデベロッパ向け解説も2つ登録されています。前号で新居さんも紹介されている「Using Oracle JDeveloper on Mac OS X」は、OracleのJDeveloperをMac OS Xで利用する方法の解説です。
「AppleEvent Manager」
http://developer.apple.com/releasenotes/Carbon/AppleEvents.html
「WebObjects 5.2 Release Notes」(PDFあり)
http://developer.apple.com/documentation/WebObjects/ReleaseNotes/index.html
「Using Oracle JDeveloper on Mac OS X」(解説)
http://developer.apple.com/tools/jdeveloper.html
「Tiger Developer Overview Series: Developing Dashboard Widgets」(解説)
http://developer.apple.com/macosx/tiger/dashboard.html
前回から12月17日の期間中、新規のテクニカルノートは2つ登録されました。
「OpenGL Performance Optimization : The Basics」では、OpenGL APIに強く依存しているアプリケーションの最適化手順をProfiler、Driver Monitor、CHUDなどのツールの使い方を含めて詳しく解説しています、また「Mac OS X Debugging Magic」の方はプリントアウトすると27ページにもなる大作で、Mac OS Xのデバッグ方法の集大成です。両方とも関連デベロッパーにとっては必読のテクニカルノートです。TN2124の方は、前号の新居さんの記事も参照してみてください。
TN2124「Mac OS X Debugging Magic」
TN2093「OpenGL Performance Optimization : The Basics」
http://developer.apple.com/technicalnotes/index-rev-date.html
新しいテクニカルQ&Aの方は6つ登録されました。QA1355とQA1395は、新居さんが前号で紹介されています。
QA1346「Finding an NSView’s current magnification」
QA1353「NSOpenGLView redraw problems after a window is closed and re-opened」
QA1395「Hang launching signed Applets from JavaScript」
QA1355「Why aren’t my tracking rects working?」
QA1374「Obtaining the name of an external MIDI Device from a MIDI Endpoint」
QA1166「OpenGL Sample Code」
http://developer.apple.com/technicalqas/index-rev-date.html
【サンプルソースコード】
前回から12月17日の期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードが2つ登録されました。「QuickTimeMovieControlは、久しぶりに登録されたQuickTime関連のサンプルソースコードです。
CreateMovieControl()を利用することでMovieの再生を行うCarbonアプリケーションの最新サンプルです。サンプルアプリのアイコンに注目しましょう(笑)。
「DNSServiceMetaQuery」(Network関連)
「QuickTimeMovieControl」(QuickTime関連)
http://developer.apple.com/samplecode/index-rev-date.html
【デベロップメント SDK】
前回から12月17日の期間中、Apple社のSDKサイトには新しいSDKはひとつも登録されませんでした。
http://developer.apple.com/sdk/
MOSAからのお知らせと編集後記は割愛します