初めてObjective-Cのコードを開くと、まず目に入るものがあります。
それは、あちこちに付いているアットマーク(@)です。
@interfaceや@property、さらには文字列まで@“Hello”のように書きます。初めて見ると「これ、タイプミスでは?」と思うかもしれません。
しかし、この@には明確な理由があります。
Objective-Cの@は、コンパイラに「ここからは純粋なCではなく、Objective-Cの拡張構文です」と知らせる合図です。
今日は、なぜこのアットマークが@interfaceにも@propertyにも@“文字列”にも同じように付くのか、その仕組みをわかりやすく解説します。
Objective-Cの@とは一体何?
まず要点から説明します。
@は「これはObjective-C独自の構文だ」とコンパイラに示す特別な記号です。
これを理解するには、Objective-Cの成り立ちを知る必要があります。
Objective-Cはまったく新しい言語ではありません。C言語にオブジェクト指向機能を追加した言語です。
つまり、C言語を100%含みつつ、クラスやメッセージなどの機能を追加した構造です。
ここで一つ問題が生じます。
コンパイラは、元からあるC構文と新たに追加されたObjective-C構文を区別しなければなりません。
その境界線を示す記号が@だったのです。
なぜアットマーク(@)だったのか?
アスタリスク(*)もシャープ(#)もあるのに、なぜわざわざ@なのでしょうか?
答えは意外にも実用的です。
C言語の標準構文では、@記号はどこにも使われていないからです。
Cで使われる文字を思い出してみましょう。
- 変数・関数名:英字、数字、アンダースコア(_)
- 演算子:+、-、*、/、=、&など
- プリプロセッサ:#(例:#include)
この一覧のどこにも@はありません。
だからObjective-Cの開発者は@を採用しました。既存のCコードと決して衝突しない安全な記号だったからです。
もし@の代わりにinterfaceという単語をキーワードにしていたら、interfaceという名前の変数を使っていた既存のCコードはすべて壊れていたでしょう。
前に@を付けることで、そのような衝突を根本から防げます。
簡単に言えば、@はObjective-C専用構文をまとめて入れておく、別の引き出しの取っ手のようなものです。
@interface・@property・@“文字列”がすべて@で始まる理由
ここから本題です。一見性質の違う三つが、なぜ同じ@で始まるのかを見ていきましょう。
結論から言えば、三つとも「Cにはなく、Objective-Cにだけある機能」だからです。
一つずつ見ていきます。
@interface — クラスの骨格(宣言)を始めるディレクティブです。Cにはクラスという概念自体がないため、@で示す必要がありました。対になる@implementationや@endも同じ理由です。
@property — オブジェクトのプロパティを自動生成する機能です。これも純粋なCにはない構文なので、@が付きます。
@“文字列” — これが最も興味深い例です。引用符だけの「Hello」と@“Hello”は、まったく別のものです。
表で比較してみましょう。
| 区分 | “Hello” | @“Hello” |
|---|---|---|
| 正体 | Cスタイルの文字配列 | NSStringオブジェクト |
| 所属 | 元来のC構文 | Objective-C拡張 |
| 機能 | 単純な文字の並び | lengthなどのメソッドを利用可能 |
引用符の前に@を一つ付けるだけで、単なる文字のまとまりが「オブジェクト」に変わります。
だから@が必要なのです。「この文字列を単なるC文字列ではなく、NSStringオブジェクトとして作って」という指示にあたります。
まとめると、こうなります。
@interfaceでも@propertyでも@“文字列”でも、すべて「Cにはなく、Objective-Cにだけある機能」なので、同じ@が付いています。
コードで一目で確認
言葉だけでは少し抽象的なので、短い例を用意しました。
以下は簡単なクラス宣言です。@がObjective-C構文をどのように囲んでいるか見てみてください。
@interface Person : NSObject // クラス宣言の開始 (CCにはない構文)
@property NSString *name; // プロパティの自動生成
@end // 宣言の終了
NSString *greeting = @"こんにちは"; // 引用符の前 @ → NSString オブジェクト
見てのとおり、@で始まる行はすべてObjective-Cが新たに追加した機能です。
反対に、@のない部分はC言語からそのまま受け継いだ構文です。
このように@の有無を見るだけで、「あ、これはObjective-Cの拡張だ」とすぐに見分けられます。
よくある質問(Q&A)
Q. @はプリプロセッサの#と同じですか?
いいえ。#includeの#はコンパイル前に処理されるプリプロセッサディレクティブです。一方、@はコンパイラが直接解釈するObjective-Cコンパイラディレクティブ(directive)なので、役割が異なります。
Q. @の種類はこれ以外にも多いですか?
はい、かなりあります。@protocol、@selector、@try/@catch、@autoreleasepoolなどさまざまです。最新の構文では、@[]配列、@{}辞書、@42のような数値オブジェクトまで@で簡単に作れます。
Q. Swiftにも@がありますよね?
そうです。ただし意味は少し異なります。Swiftの@は、@Stateや@IBOutletのように、主に属性(アトリビュート)の表示に使われます。起源は似ていますが、用途は区別して考えるとよいでしょう。
コードのあちこちに付いたアットマークは見慣れないかもしれませんが、「CとObjective-Cを分ける境界線」だと分かれば、むしろ親しみやすく見えてきます。
@を追うだけでも、どこからオブジェクト指向構文が始まるのかが一目で分かります。Objective-Cのコードを読むときは、この見方を一つ覚えておくだけで、ずっと楽になります。今日も楽しいコーディングを!

