Swiftにおける Voidと空Tuple - ()

はじめに

本日、UZUMAKIさん主催の「iOSアプリ設計パターン入門」の勉強会に参加しました。

内容はMVVMアーキテクチャに関してでしたが、議論の中でVoidや()の扱いに関して面白いものがでてきたので備忘もかねて記載します。

環境設定

以下の環境を使用しています。

  • Xcode10.0
  • Swift4.2

Void と 空Tupleについて

Voidは以下の形式で表される「型」です。

public typealias Void = ()

そのため、メソッドの引数等にとることはできません。 その際にはInstanceを入れる必要があります。 多くの場合、このような場合の引数として () を使用すると思います。

let sampleRelay = PublishRelay<Void>()

// このように Voidで型指定されている部分に ( ) を入れる。
sampleRelay.accept(()) 

ただ、 Voidが () の typealiasであることから、以下のように () は型としても機能します。

let a: () = ()

また、 Voidは型であるため以下のようにインスタンス化も可能です。

let a = Void()

したがって、 ()を代入する箇所では Void()の代入でも代替可能です。 ただ、 Void()はできますが、 ()()はできません。 Cannot call value of non-function type '()'というエラーが表示され、コンパイルエラーとなります。

まとめ

以上、取り止めがないですがまとめると下記のようになることがわかりました。

// Void は 型、 ()は型としてもインスタンスとしても機能する

let a: () = ()  // OK
let b = ()  // OK
let c = Void() // OK
let d: Void = () // OK
let e = ()() //  NG
let f: () = ()() //  NG

この辺りの言語仕様は普段あまり意識しませんが、色々触ってみると面白いですね。 個人的にはVoidがインスタンス化可能であることが意外でした。