iOSアプリ開発初心者のためのオブジェクト指向の基本iOS SDKで始めるObjective-C入門(6)(3/4 ページ)

» 2014年03月17日 18時00分 公開
[平井祐樹,クラスメソッド]

情報隠ぺい「カプセル化」とは

 次に、記事「オブジェクトに必要な4つの特性とは?」にある「カプセル化」について考えてみましょう。この記事ではカプセル化の例の1つとして、「公開されている「インターフェース」以外にオブジェクトの状態に直接アクセスできない(情報隠ぺい)」とあります。実は、これもすでに実現しています。

カプセル化の例(記事「オブジェクトに必要な4つの特性とは?」より引用)

 例えば、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
リスト8 Person.h
#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
リスト9 Person.m

 併せて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
リスト10 ViewController.m

 これを実行すると、コンソールに以下のように実行されます。

 このとき、性と名の間にスペースを入れたくなったとします。その場合は、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
リスト11 Person.m

 実行結果は以下のようになります。

 このように、Objective-Cでは、カプセル化を実現できることが分かります。

クラスが他のクラスの特性を引き継ぐ「継承」とは

 人間にもたくさんの種類があります。例えば、日本人、アメリカ人などのように国籍別、またはSE、警察官などのように職業別に分類できます。オブジェクト指向では、これらの「関係」を表せます。

 例えば、学生というクラスを考えてみましょう。学生は学校名、学科、学年などさまざまなメンバー変数を持つことが考えられます。これらのメンバー変数はPersonクラスには定義されておりません。しかし、学生も人間です。

 この関係を表すために、オブジェクト指向では「継承」という概念を用います。継承を用いることで、あるクラスが他のクラスの特性を引き継ぐことができます。ですから、学生クラスは人間クラスを継承することで、人間クラスの特性を引き継ぐことができます。

 このとき、人間クラスは「スーパークラス」「抽象クラス」「親クラス」などのように表現します。学生クラスは「サブクラス」「派生クラス」「子クラス」などのように表現します。

 また、このことを「サブクラス化」ともいいます。

「スーパークラス」と「サブクラス」の例(記事「複雑なものを単純に〜分類と分解〜」より引用)

 それでは、早速学生クラスを作ってみましょう。クラスの名前はStudentとします。作り方はPersonクラスの時と同じです。Personクラス作成時と異なる点は、クラス名を入力する画面で、[Class]に「Student」、[Subclass of]に「Person」を入力します。

 Studentクラスを作成したら、Student.hを開いてみましょう。

#import "Person.h"
@interface Student : Person
@end
リスト12 Student.h

 「@interface Student : Person」とありますが、これが「学生クラスは人間クラスを継承する」ということを意味しています。

 ところで、学生は学校名、学科、学年などさまざまなメンバー変数を持つことが考えられると話しました。ここでは、学校名を定義するメンバー変数を持つこととします。

 Student.hとStudent.mを以下のように変更します。

#import "Person.h"
@interface Student : Person
{
    // 学校名
    NSString *_school;
}
// 学校名を取得する
- (NSString *)school;
// 学校名を設定する
- (void)setSchool:(NSString *)school;
@end
リスト13 Student.h
#import "Student.h"
@implementation Student
// 学校名を取得する
- (NSString *)school
{
    return _school;
}
// 学校名を設定する
- (void)setSchool:(NSString *)school
{
    _school = school;
}
@end
リスト14 Student.m

 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
リスト15 ViewController.m

 実行すると、以下のようにコンソールに表示されます。

 このように、StudentクラスはPersonクラスを継承しているため、Studentクラスに定義されていない名前に関するメンバー変数やメソッドを使用できます。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。