LoginSignup
69
72

More than 5 years have passed since last update.

[Objective-C] クラス拡張と無名カテゴリ

Last updated at Posted at 2014-02-22

この記事にリンクして、詳細に書いてくれている記事があったので紹介。

クラス拡張とカテゴリの違いの話。

Objective-Cの内部実装にも触れて分かりやすく書いてくれているので、より どういう違いがあるかが分かるかと思います。


AppleのiOS View Controllerプログラミングガイドを読んでいて気づいた。
なんで実装ファイルの方で@interfaceを宣言しているんだろうと思っていたのだけど、これはどうやら クラス拡張 というものらしい。

似たような仕組みに、 カテゴリ がある。
カテゴリは@interface Hoge(anyCategory)で宣言するやつ。
これを無名にしている(つまり@interface Hoge())のが、実装ファイルでよく書かれているやつだ。

なるほど、無名カテゴリだから()なのか。
と腑に落ちたことをTwitterでつぶやいたら、「いや、厳密には違う」と指摘をもらった。
調べてみたら、どうやら クラス拡張 という機能で、カテゴリとは厳密には違う仕組みのよう。

参考にした記事から引用させてもらうと、

クラス拡張は、無名のカテゴリに似ています。が、別物です。一番の違いは、インスタンス変数を宣言できることと、宣言したメソッドはクラス本体の(=カテゴリ無しの)@implementationで実装しなければならない点です。

ということらしい。
確かに外部に公開しないメソッドとかを宣言していたなーと気づいた。

つまりまとめると、

  1. 実装ファイルに書かれている@inteface部は クラス拡張 の宣言
  2. 実装ファイルの@implementationカテゴリなし の実装部分のため、クラス拡張の宣言をしっかりと実装しているために問題なし

ということか。

サンプルコード

// Hoge.h
#import <Foundation/Foundation.h>

// 公開メソッド
@interface Hoge : NSObject
- (void)foo;
- (void)bar;
@end
// Hoge.m
#import "Hoge.h"

// クラス拡張
// ヘッダーに公開されないメソッドとインスタンス変数
@interface Hoge () {
    int _count;
}
- (void)method;
@end

@implementation Hoge
- (void)foo { }
- (void)bar { }
- (void)method { }
@end

コメントもらったので追記

よく使われるテクニックとして、ヘッダにreadonlyのプロパティを宣言しておき、外部からは読み取り専用にしつつ、実装側のクラス拡張機能でreadwriteにして読み書きできるようにする、というものがあるみたいです。確かに便利そう!

参考にさせてもらった記事は以下です。

69
72
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
69
72