修正日: 07/07/13
練習問題8
CalcBMIみたいなのを作ってみよう! その4
今回はインスタンス変数について説明します。これを理解する為に、まずは変数の「スコープ」という考え方について簡単に紹介しておきます。
いままで変数は各メソッド/関数で最初に定義して、処理が終わったら変数も消える、という形でずっと使っていました。
int functionA( void )
{
int i;
//何か処理
} //ここでiは消えてしまう
functionAの中で宣言した変数はその関数の中でのみ有効である(参照できる)という決まりがあるからです。この変数の有効範囲のことを「スコープ」といいます。まあ呼び方自体はどうでもいいのですが、変数がどこからどこまで有効なのか、という点については注意してください。関数の中で宣言した変数は関数の中で使える、ということを覚えておけば大体間違いないのですが、if{}やfor{}の中で変数を宣言するとスコープはその{}の中になるので注意してください。例えば
int functionA( void )
{
int i = 2;
if( i == 2 )
{
int j = 3;
//何か処理
} //jはここで消える
//続けて何か処理
} //ここでiは消える
という感じです。if{}から出たあとにjを参照することはできません。引き続きjを使いたい場合はif{}の外で宣言してあげる必要があります。それならはじめに全部宣言すれば良いじゃないか、と思う人もいると思いますが、はじめに大量の変数を宣言するよりも、必要なところで必要なだけ変数を宣言した方がソースコードはずっと読みやすくなります。まあそこら辺はいろいろ作っているうちに慣れてくると思いますので、まずは変数の有効範囲について注意してください。
ただ、変数がこのように毎回毎回消えてしまってはいかにも不便です。アプリケーションの状態などを記録しておくためにはどうすればいいでしょうか?Cocoaではオブジェクトのインスタンス変数というものを使います(C言語由来のグローバル変数も使えますが、一般的ではありません)。インスタンス変数とは文字通り各クラスのインスタンスが持っている変数のことで、関数やメソッドの実行とは関係無しに値が保持されます。具体的にはインスタンスオブジェクトが生成された時に宣言され、インスタンスオブジェクトが解放される時に、インスタンス変数も消滅します。インスタンス変数のスコープは所属するオブジェクトが存在する間、といえるでしょう。
ではまずは宣言の仕方を見てみましょう。
@interface BMIController : NSObject
{
IBOutlet id bmiWindow;
//略
float weight;
float height;
float bmi;
}
インスタンス変数の宣言はこのようにヘッダファイルのクラス定義のところに書きます。このBMIControllerは三つのfloatの変数を持っています。このインスタンス変数を利用するには、例えば、
- (IBAction)changeHeight:(id)sender
{
height=[sender floatValue];
}
あるいは
- (void)calcBMIAndSet
{
bmi=calculateBMI(height, weight);
[bmiField setFloatValue:bmi];
}
のように直接値を取り出したり、代入したりすればOKです。放っておいても値は消えません。インスタンスメソッドは当該クラスの中のメソッドからは自由に参照することができます。ただし関数からは参照することはできません。
また別のオブジェクトから直接参照することもできません。あるオブジェクトから別のオブジェクトのインスタンス変数を参照するためには「アクセッサメソッド」と呼ばれるメソッドを使います。もう何度も使ったことがありますね。NSTextFieldの「intValue」と「setIntValue:」がそうです。あれはNSTextFieldのインスタンス変数を取り出したりセットしたりするためのアクセッサメソッドです。
ということでようやく今回の課題。前回まで作ってきたCalcbmiにこのインスタンス変数を取り入れてうまく書き直してみてください。ソースコードが少しすっきりしてみやすくなると思います。
解答はこちら