Swift & Objective-C

Objective-Cのアットマーク(@)構文:なぜすべて@で始まるのか?(完全まとめ)

初めてObjective-Cのコードを開くと、まず目に入るものがあります。

読了 5 分
Objective-Cのアットマーク(@)構文:なぜすべて@で始まるのか?(完全まとめ)のカバー画像

初めて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専用構文をまとめて入れておく、別の引き出しの取っ手のようなものです。

C由来のものとObjective-Cが追加したものの境界を示す@
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のコードを読むときは、この見方を一つ覚えておくだけで、ずっと楽になります。今日も楽しいコーディングを!