読者です 読者をやめる 読者になる 読者になる

【Swift】Appleの新言語「Swift」のリファレンスを読む(19) - Dynamic Type、Attribute、Special Literals

注意

  • あくまでメモ書きなので細かい部分を端折りますし、色々間違ってるかもしれません。ちゃんとした内容は原文を読んでね。
  • コード例は基本的に原文からそのまま引用していますが、ちょっとした注釈をつけたり、統合したりしています。
  • SyntaxHighlighterが対応してないので微妙に読みにくいです。SyntaxHighlighterはこちらのものを使用させて頂いてます。
  • 他言語にそっくりな部分でも指摘しない。(自戒)

Dynamic Type

Dynamic Typeに関してはTypesと言う章のMetatype Typeと言うセクションに記述されています。

先にコード例を見てみましょう。

class SomeBaseClass {
    class func printClassName() {
     println("SomeBaseClass")
 }
}

class SomeSubClass: SomeBaseClass {
    override class func printClassName() {
     println("SomeSubClass")
    }
}

let someInstance: SomeBaseClass = SomeSubClass()
// someInstance is of type SomeBaseClass at compile time, but
// someInstance is of type SomeSubClass at runtime

someInstance.dynamicType.printClassName()
// prints "SomeSubClass"

ここでsomeInstanceはSomeBaseClassとして宣言されています。が、実体はSomeBaseClassを継承したSomeSubClassです。

someInstance.printClassNameを呼び出すとSomeBaseClassの方の静的メソッドを呼び出してしまいますが、間にdynamicTypeを挟むことによってSomeSubClassの方の静的メソッドを呼び出すことができます。

静的メソッドのオーバーライドを完全にサポートするなんて随分マニアックなところをフォローするなぁと思うんですが、最近の言語はそんなもんなんでしょうか。

Attributes

所謂「属性」とか「注釈」として扱われるあれですね。

驚いたことに、この手の機能にしては珍しくオリジナルのものを作成することはできません。ちょっと信じられないので色々調べてみたんですが、文句を言ってる人すらあんまり見かけません。まぁまだメタプログラミングとかリフレクションとか考える段階でもないっちゃないんですが、欲しくないですか?普通に。それとももっといい機能があるのかな?

気を取り直して解説していきましょう。

Attributeは何かしらの宣言時、もしくは型そのものにのみ付与することができます。自作できないのでてっきりこのドキュメントに全部載ってるのかな?と思ったら、他の章で何度か見かけたlazyとかがないので、もうなんか、これを説明する気があんまりなくなってきました…。

Declaration Attributes

assignment

演算子のオーバーロードや自作の演算子を定義するときに使います。

class_protocol

プロトコルがクラスにのみ適合可能なことを示します。クラスメソッドとかクラスプロパティが定義されてるときに使うんですかね。また、objcと言うAttributeが付与されている場合はつけなくていいそうです。

noreturn

functionやmethodに付与します。文字通り「呼ばれても何の値も返しませんよ」と言うことを示します。

これがついていてもオーバーライドは可能ですが、当然ながらオーバーライドしたものでもnoreturnである必要があります。

NSCopying

クラスのプロパティに付与します。Objective-Cのcopyと言うAttributeと似た性質を持つらしいです。

これが設定されているプロパティのsetterではプロパティ自身の値ではなく、それをコピーしたものが用いられるそうです。内部でcopyWithZoneと言うメソッドを使うからか、このAttributeが設定されるプロパティの型はNSCopyingと言うプロトコルに適合している必要があります。

NSManaged

CoreDataと呼ばれる仕組みの互換性のためにあるAttributeみたいです。「これはNSManagedObject(あるいはそれを継承したクラス)のプロパティですよ」と言うことを示すようです。

objc

Objective-Cとの相互運用を行うためのAttributeです。

クラスやプロトコルの宣言時にこれを付与すると、暗黙的にそのメンバ(プロパティとかメソッドとか)も相互運用の対象となります。

クラスの場合であれば自動で親クラスも相互運用の対象としてくれるんですが、プロトコルの場合は自分で親プロトコルにもobjcをつけないといけません。

また、引数を渡すことでObjective-C側で使用する際の別名をつけることができます。

@objc
class ExampleClass {
    var enabled: Bool {
    @objc(isEnabled) get {
     // Return the appropriate value
    }
    }
}

上記の例であれば、ExampleClass.isEnabledでenabledの値を取得できる、と言うことです。

UIApplicationMain

Objective-CにおけるAppDelegateのようなものらしいです。いや、よく知らないんですが。

要はエントリポイントの明示的な指定、ですかね。これが指定されていない場合は「main.swift」ファイルの「main」と言う関数を呼ぶそうです。

他にもInterface Builderと関連付いたIBAction、IBDesignable、IBInspectable、IBOutletと言ったAttributeがあるそうです。Attributeの自作はできないのに開発ツールのためのAttributeがあるあたり邪悪って感じですね。(プログラマ向けジョークです)

Type Attributes

auto_closure

遅延初期化のための式を自動でクロージャにしてくれます。TypesFunction Typeと言うセクションに細かい説明が載っています。

func simpleAssert(condition: @auto_closure () -> Bool, message: String) {
    if !condition() {
     println(message)
    }
}

let testNumber = 5
simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")
// prints "testNumber isn't an even number."

中々便利そうです。この例ではあんまり意味なくね?って言うのはともかくとして。

noreturn

さっき説明したので割愛。

Special Literals

Expressionsと言う章のPrimary Expressionsと言うセクションの一番上に書いてあります。

リテラル
__FILE__ String ファイル名
__LINE__ Int 行番号
__COLUMN__ Int 列番号
__FUNCTION__ String 関数名

なんと言うかまぁ、環境変数みたいなものです。デバッグ用ですね。

__FUNCTION__で取得できる値はプロパティのgetter / setterであればプロパティ名、と言ったように、コンテキストによって変わります。

まとめ

前回の記事から一ヶ月も経ってしまいました。忙しかったと言うか…その…やめましょう、この話は。

のんびり書いていたせいでリファレンスもいつのまにか三版になってしまっています。過去の記事を修正する予定と暇は今のところないです。が、ArrayとDictionaryの揉め事は私も知っているので、そこぐらいは直すかもしれません。…一年後とかに。

第一回の前書きでも言いましたが、個人的な理由でこの言語を使うことは多分ないでしょう。

Objective-Cも一切触ったことがないし、言ってしまえばApple製品で持っているものは一つもない(嫌いとかそう言うわけではなく、縁がない)んですが、世界でこれだけのシェアを誇る端末のソフトウェア開発用に生み出された言語がどんな思想・美学を持っているかを垣間見れればそれでいいかなと思っていたので、十分でしょう。

APIにもがっつり踏み込んでいきたい気持ちは若干あるんですが、やはりそんな暇はありません。何かの間違いでSwiftによる開発をしなければならなくなったら書くかもしれませんが。

参考