書いて覚えるSwift入門

第5回 遺産の継承(その2)

この記事を読むのに必要な時間:およそ 4 分

AnyObjectとAnyの違い

SwiftのAnyObjectは,Objective-Cにおけるidに相当します。id同様なんでも入りますが,適切に使うにはisで適切な型を判定したり,asで適切な型に変換したりしなければなりません。

また,CocoaUIKitなど,Objective-C由来のフレームワークをimportしておく必要もあります図2⁠。

import Cocoa
var ao:AnyObject
ao = "assign"
// ao += " any value" // error
ao = (ao as String) + " any value"
ao = 40
// ao += 2            // error
ao = (ao as Int) + 2

図2 AnyObjectの実行例

図2 AnyObjectの実行例

ところがSwiftにはAnyObjectとは別にAnyという型も存在します。前述のAnyObjectAnyに変えてもそのまま動いてしまいますしimport Cocoaをコメントアウトしてもそのまま動いてしまいます図3⁠。

図3 Anyの実行例

図3 Anyの実行例

なぜ,Swiftには「なんでもありな型」が2つも存在するのでしょう?

sizeof()で双方の型を見てみると,面白いことがわかります。64bitプラットフォームではsizeof(AnyObject)は8なのに対し,sizeof(Any)は32。AnyObjectは1ワード,Anyは4ワードです。賢明な読者であれば,この時点で予想がつくでしょう。AnyObjectは参照,つまりclassであるのに対し,Anyは実値,つまりstructなのです。

さらに「禁断の組込み関数⁠⁠,unsafeBitCastを使ってAnyがどうなっているのかを見てみましょうリスト7,図4⁠。

リスト7 unsafeBitCastでAnyの動きを調べる

import Cocoa
let s = "Swift"
var a:Any
a = s
var aq = unsafeBitCast(a, (UInt,UInt,UInt,UInt).self)
var sq = unsafeBitCast(s, (UInt,UInt,UInt).self)
let i = 42
a = i
aq = unsafeBitCast(a, (UInt,UInt,UInt,UInt).self)
var a1 = unsafeBitCast((42,0,0,aq.3), Any.self)
a as Int == a1 as Int

図4 リスト7の実行例

図4 リスト7の実行例

なんのことはない。4ワードのうち頭から本来の値を詰め込んだうえで,最後の1ワードに「型ID」が入っているだけのです。SwiftのStructは,IntDoubleが1ワード,関数が2ワード,StringArrayDictionaryが3ワードなので,Anyの中にすべて納まります。

これに対し,AnyObjectの正体は,Objective-Cで書けばid *オブジェクトへのポインタで,型情報はAnyのように値そのものの一部ではなくその参照先に格納されています。

それではAnyはどこで使われているかというと,Xcodeの内部です。Xcodeは現在書かれているコードにあわせて振る舞いを変えますが,この振る舞いを受け取る関数は当然ありとあらゆる型を受け取れなければなりません。Swiftにはreflect()という関数がありますが,これがAnyを活用している関数の1つで,これを用いると内観(introspect)するためのコードを自作することもできます。

しかしそうでもない限り,Anyを使うケースはほとんどないでしょう。以前紹介したようにSwiftには総称関数とプロトコルがあるので,静的型の特長を活かすためにもAnyの使用は避けるべきです。まとめると次のようになるでしょう。

  • AnyObjectは,Objective-Cで書かれたフレームワークの連携においてのみ使う
  • Anyは使わない(複数の型を受け付けるコードには,総称関数とプロトコルを用いる)

続きは次号

今回はSwiftからObjective-Cのフレームワークを用いる例としてSwift-JSONを紹介し,AnyObjectAnyの違いを垣間見ました。次回はXcodeでCおよびObjective-CのコードとSwiftのコードを同一のプロジェクトで連携する例を見ていくことにします。

Software Design

本誌最新号をチェック!
Software Design 2019年11月号

2019年10月18日発売
B5判/184ページ
定価(本体1,220円+税)

  • 第1特集
    ターミナルからクラウド管理自由自在
    Microsoft Azureで最新Webアプリ開発
    [Mac x bash]⁠Windows x WSL 2]⁠Visual Studio Code]⁠Windows Terminal]
  • 第2特集
    環境構築から使い方まで実践指導!
    脆弱性スキャナVuls/Trivy/Dockle
    OSSを公開したら人生が変わった3人の開発者
  • 短期集中連載
    Webエンジニアのための時短スマホアプリ開発
    【1】アプリ開発を継続するためにReact Native+Expoをお勧めするわけ

著者プロフィール

小飼弾(こがいだん)

1969年生まれ,東京都出身。元ライブドア取締役の肩書きよりも,最近はPokemon GOのガチトレーナーのほうが有名になりつつある……かもしれない永遠のエンジニアオヤジ。

活躍の場はIT業界だけでなく,サブカルからアカデミックまで多方面にわたり,ネットからの情報発信は気の向くまま毎日毎秒! https://twitter.com/dankogai,ニコニコチャンネルは,http://ch.nicovideo.jp/dankogai,blogはhttp://blog.livedoor.jp/dankogai/

当社刊行書籍は『小飼弾のアルファギークに逢ってきた』『小飼弾のコードなエッセイ』など。他にも著書多数。