次に、記事「オブジェクトに必要な4つの特性とは?」にある「カプセル化」について考えてみましょう。この記事ではカプセル化の例の1つとして、「公開されている「インターフェース」以外にオブジェクトの状態に直接アクセスできない(情報隠ぺい)」とあります。実は、これもすでに実現しています。
例えば、ViewControllerクラスとPersonクラスについて考えてみましょう。ViewControllerからはPersonクラスの属性である_nameや_ageを勝手に変更することはできません。
_nameを変更するには「- (NSString *)nameメソッド」や「- (void)setName:(NSString *)name」メソッドを介してのみ行えるようになっています。
また、Person.hとPerson.mを以下のように変更してみましょう。
- #import <Foundation/Foundation.h>
- @interface Person : NSObject
- {
- // 性
- NSString *_lastName;
- // 名
- NSString *_firstName;
- }
- // 性を設定する
- - (void)setLastName:(NSString *)lastName;
- // 名を設定する
- - (void)setFirstName:(NSString *)firstName;
- // 名前を取得する
- - (NSString *)name;
- @end
- #import "Person.h"
- @implementation Person
- // 性を設定する
- - (void)setLastName:(NSString *)lastName
- {
- _lastName = lastName;
- }
- // 名を設定する
- - (void)setFirstName:(NSString *)firstName
- {
- _firstName = firstName;
- }
- // 名前を取得する
- - (NSString *)name
- {
- return [NSString stringWithFormat:@"%@%@", _lastName, _firstName];
- }
- @end
併せてViewController.mを以下のように変更します。
- #import "ViewController.h"
- // Personクラスをインポートする
- #import "Person.h"
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Personクラスのインスタンスを生成する
- Person *yuki = [[Person alloc] init];
- // 性を設定する
- [yuki setLastName:@"平井"];
- // 名を設定する
- [yuki setFirstName:@"祐樹"];
- // 名前をコンソールに表示する
- NSLog(@"こんにちは、私の名前は%@です。", [yuki name]);
- }
- @end
これを実行すると、コンソールに以下のように実行されます。
このとき、性と名の間にスペースを入れたくなったとします。その場合は、Personクラスの「- (NSString *)name」メソッドのみ変更すればよく、ViewControllerに一切手を加える必要はありません。
- #import "Person.h"
- @implementation Person
- // 性を設定する
- - (void)setLastName:(NSString *)lastName
- {
- _lastName = lastName;
- }
- // 名を設定する
- - (void)setFirstName:(NSString *)firstName
- {
- _firstName = firstName;
- }
- // 名前を取得する
- - (NSString *)name
- {
- return [NSString stringWithFormat:@"%@ %@", _lastName, _firstName];
- }
- @end
実行結果は以下のようになります。
このように、Objective-Cでは、カプセル化を実現できることが分かります。
人間にもたくさんの種類があります。例えば、日本人、アメリカ人などのように国籍別、またはSE、警察官などのように職業別に分類できます。オブジェクト指向では、これらの「関係」を表せます。
例えば、学生というクラスを考えてみましょう。学生は学校名、学科、学年などさまざまなメンバー変数を持つことが考えられます。これらのメンバー変数はPersonクラスには定義されておりません。しかし、学生も人間です。
この関係を表すために、オブジェクト指向では「継承」という概念を用います。継承を用いることで、あるクラスが他のクラスの特性を引き継ぐことができます。ですから、学生クラスは人間クラスを継承することで、人間クラスの特性を引き継ぐことができます。
このとき、人間クラスは「スーパークラス」「抽象クラス」「親クラス」などのように表現します。学生クラスは「サブクラス」「派生クラス」「子クラス」などのように表現します。
また、このことを「サブクラス化」ともいいます。
それでは、早速学生クラスを作ってみましょう。クラスの名前はStudentとします。作り方はPersonクラスの時と同じです。Personクラス作成時と異なる点は、クラス名を入力する画面で、[Class]に「Student」、[Subclass of]に「Person」を入力します。
Studentクラスを作成したら、Student.hを開いてみましょう。
- #import "Person.h"
- @interface Student : Person
- @end
「@interface Student : Person」とありますが、これが「学生クラスは人間クラスを継承する」ということを意味しています。
ところで、学生は学校名、学科、学年などさまざまなメンバー変数を持つことが考えられると話しました。ここでは、学校名を定義するメンバー変数を持つこととします。
Student.hとStudent.mを以下のように変更します。
- #import "Person.h"
- @interface Student : Person
- {
- // 学校名
- NSString *_school;
- }
- // 学校名を取得する
- - (NSString *)school;
- // 学校名を設定する
- - (void)setSchool:(NSString *)school;
- @end
- #import "Student.h"
- @implementation Student
- // 学校名を取得する
- - (NSString *)school
- {
- return _school;
- }
- // 学校名を設定する
- - (void)setSchool:(NSString *)school
- {
- _school = school;
- }
- @end
Studentクラスを変更したら、ViewController.mを以下のように変更します。
- #import "ViewController.h"
- // Studentクラスをインポートする
- #import "Student.h"
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Personクラスのインスタンスを生成する
- Student *yuki = [[Student alloc] init];
- // 性を設定する
- [yuki setLastName:@"平井"];
- // 名を設定する
- [yuki setFirstName:@"祐樹"];
- // 学校名を設定する
- [yuki setSchool:@"アイティメディア学園"];
- // 名前と学校名をコンソールに表示する
- NSLog(@"こんにちは、私の名前は%@です。%@に所属しています。", [yuki name], [yuki school]);
- }
- @end
実行すると、以下のようにコンソールに表示されます。
このように、StudentクラスはPersonクラスを継承しているため、Studentクラスに定義されていない名前に関するメンバー変数やメソッドを使用できます。
Copyright © ITmedia, Inc. All Rights Reserved.
Smart & Social 鬮ォ�ェ陋滂ソス�ス�コ闕オ譁溷クキ�ケ譎「�ス�ウ驛「�ァ�ス�ュ驛「譎「�ス�ウ驛「�ァ�ス�ー