Objective-C Primer 番外編 9.オブジェクト〜カプセル化〜

最終更新日時5/25/23:30
atoi()関数のための stdlib.h ヘッダファイルの読み込みを忘れていました。サンプルコードを修正したものに変更しました。 5/26/00:00

今回は、
1. カプセル化
2. ポリモルフィズム [polymorphism](多態性)
を説明する予定でしたが、ポリモルフィズムはObjective-Cにおいてはメッセージ式の左側(オブジェクト)が違えば右側のメソッドが同じでも構わない。というだけのことです。
メッセージ式
[オブジェクト   メソッド]
左側のオブジェクトのところをレシーバーとも呼びますが、レシーバーが違えば右側のメソッド(セレクタとも呼ぶ)が同じでも構いません。これは違う関数で同じ名前のローカル変数が存在していても問題ないのと同じことだと思っていただいて結構です。
次にカプセル化も難しい概念ではありません。一番難しいところはいつのまにか過ぎたみたいです。

サンプルコードは seito2m.zip からダウンロードできます。



seito2.m
d0122908_0123829.gif
main関数の do-while文(52行目から55行目)を見て下さい。前回のseito1.mと比べるとずいぶんスッキリしました。
ここでやっていることは、
1. 53行目で「点数は:」と尋ねる
2. 54行目でユーザーが入力した値を文字列変数ssに収める
3. 55行目でSeitoクラスのsetTensuuメソッドに文字列ssを送ってその文字列が点数として正しい値か(0から100までの数字かどうか)判定してもらう。
の3点だけです。「偽」ならまた do-while文の先頭に戻って「点数は:」と尋ねてきます。「真」なら do-while文を抜けて次の処理に進みます。

ユーザーが入力した文字列が「点数として受け取れる範囲の数字であるかどうか」の判断はすべてSeitoクラスのsetTensuuメソッドが受け持つことになりました。main関数からはSeitoクラスのsetTensuuメソッドの内部で何が行われているか知る必要はありません。たんにsetTensuuメソッドの使い方さえ知っておけば良いのです。そしてこのsetTensuuメソッドの使いかたとして知っておかなければならないことは、
1. 引数として文字列を渡す
2. 正しい点数として評価できる文字列なら「真」が返ってきて、インスタンス変数[tensuu]にその値が代入される。もし正しくなければ「偽」が返ってきて、インスタンス変数[tensuu]には何も代入されない。
の2点だけです。
このSeitoクラスの場合は自作のクラスなのでsetTensuuメソッドの中も私たちは知っていますが、実際のプログラミングで使うクラスはほとんどがCocoaフレームワークで用意されているものを使います。そしてその場合に私たちが知っておく必要のあるのはその使いかただけでそのクラスの内部構造がどうなっているのかを知る必要はありません。このようにクラス(オブジェクト)の内部構造が隠されていてそのデータ構造(インスタンス変数)に直接アクセスできないことをオブジェクトの隠蔽化もしくはカプセル化と呼びます。

 とは言ってもこのseito2.mではもうひとつピンとこないと思います。実はこのseito2.mはObjective-Cの正式のファイル構成ではなく簡略化した方式で書かれています。次に正式のObjective-Cのファイル構成で書いてみます。これを見ればカプセル化が視覚的に理解できるかもしれません。

 なお、seito2.m のターミナルでの実行方法は
  cd Desktop/vivacocoa
  cc seito2.m -framework Foundation
  ./a.out
となります。

注意:
setTensuuメソッドは前のseito1.mでは引数としてint値を送っていましたが、今回のseito2.mでは引数として文字列のままで送るように変更されています




Seito2
では、上のseito2.mを標準のファイル構成になおしたものを示します。
このファイルは seito2.zip からダウンロードすることもできます。

Seito.h
d0122908_23551175.gif
Seitoクラスのインターフェース部分だけを1つのファイル(ヘッダファイル)とします。このファイルの冒頭で NSObject や stdio などのヘッダファイルの読み込みと記号定数の設定も行っています。ファイルの拡張子が「.h」になっていることに注意してください。このヘッダファイルに記述するのは各種のプリプロセッサ(#ではじまるファイルの読み込みや記号定数)と @interface 〜 @end で記述されるインターフェース部分のみです。


Seito.m
d0122908_1514725.gif
Seitoクラスのインプリメンテーション(実装)部分のみをひとつのファイルにします。拡張子が「.m」になっていること、冒頭に「Seito.h」ヘッダファイルの読み込みが必要なことに注意してください。
 なお1行目の
  #import "Seito.h"
と、Seito.h がダブルクォーテーションで囲まれているのは「同じフォルダ内のSeito.hを読み込む」という意味になります。今までの
  #import <Foundation/NSObject.h>
  #import <stdio.h>
などのように < > で囲まれているヘッダファイルはコンパイラがその存在の場所をあらかじめ知っているファイルという意味になります
 インプリメンテーション部分とは @implementation 〜 @end で囲まれた部分のこと指します。


main.m
d0122908_159988.gif
ここでも冒頭に Seito.h ヘッダファイルを読み込んでいることに注意してください。
 このようにファイルを分割するとクラス(オブジェクト)が1つの独立したプログラムのようになっていることに気付くと思います。クラス(オブジェクト)に必要なことはすべてそのクラス(オブジェクト)内で処理できるようにします。main.mの中では単にそれを利用しているだけです。

この seito2 のターミナルでのコンパイルと実行は以下の通りになります。

1.ダウンロードした「seito2」フォルダをそのままデスクトップに置いていた場合
  cd Desktop/seito2
2.ダウンロードした「seito2」フォルダをデスクトップの[vivacocoa」フォルダに移動した場合
  cd Desktop/vivacocoa/seito2
3.次に上記の2つのどちらの場合でも
  cc main.m Seito.m -framework Foundation
  ./a.out
とします

次回は最終回です。この Seito クラスに
  1. 「名前」を設定・取得できる仕組み
  2. 「点数」から「評価」を自動で算出する仕組み
を加えます

配列と C言語における文字列の説明をわざと避けていましたが、やはり説明しておく必要を感じましたので、「付録A.配列」という説明を加えることにします。「第5回。制御文その2」と「第6回。構造体」の間ということです。



Seito.mだけコード説明しておきます
d0122908_1514725.gif

8行目。atoi()関数はCの関数です。引数の中の文字列を整数値に変換して返り値として返します。整数値に変換できない文字列の場合は0を返します。
10行目。 if文の評価式が0以外なら11行目に進みます。数字は0だけが偽として評価されることを思い出してください
11行目。if文の評価式は「数字が0未満か101以上なら」という意味です。
12行目〜13行目。11行目が真ならNO(偽)を返して呼び出し元のmain関数に戻ります。
15行目。11行目が偽なら変数 tensuu に数字を代入してそのまま27行目に進みYES(真)を返して呼び出し元のmain関数に戻ります。
16行目。数字が0だった場合はこの else句に進んできます。0の場合は本当に数字の0の場合と数字として意味をなさない文字列の場合があり、すこし手を加える必要があります。
17行目。char型変数 ch にmain関数から渡された文字列の1番目の文字を代入します
18行目。この文字が数字の0なら0点として入力されたとして変数 tensuu に0を代入して27行目に進み YES(真)を返して呼び出しもとのmain関数に戻ります
20行目。文字列の1番目が + か - で、文字列の2番目(string[1])が0なら変数tensuuに0を代入して同じく27行目に進みます
22行目。それ以外なら数字として評価できなかった文字列ということになりますので23行目で「0から100までの点数を入力してください」と表示して、24行目でNO(偽)を返して呼び出し元のmain関数に戻っています
[PR]
by vivacocoa | 2007-05-18 00:26


<< 独り言 Objective-C Pri... >>