LoginSignup
7
1

More than 1 year has passed since last update.

[Swift] structがデフォルトで持つMemberwise Initializerを使い続けたい。別のイニシャライザをextensionで追加すれば使い続けられるよ!

Last updated at Posted at 2021-05-21

問題

Memberwise Initializer

Swiftの構造体(struct)にはメンバ変数の初期化を行うイニシャライザ(Memberwise Initializer)がデフォルトで自動的に生成されます。この機能によって新しいメンバ変数を構造体に追加したとしても自動的にイニシャライザへの引数の追加が行われるため、イニシャライザの変更を手動でする必要もなく、対応漏れもありません。

struct Person {
    let name: String
    let age: Int
}

let john = Person(name:"John" , age: 18)

Memberwise Initializerが使えなくなる

ただこの便利なMemberwise Initializerは、イニシャライザを追加すると上書きされて使えなくなってしまいます。
下の例では新しく追加したbirthday:を引数にとるイニシャライザは問題なく使えるのですが、Memberwise Initializerが上書きされてしまい、使おうとするとエラーが出てしまいます。Xcodeではサジェストもされません。

struct Person {
    let name: String
    let age: Int

    init?(name: String, birthday: Date) {
        let today = Date()
        let dateComponents = Calendar.current.dateComponents([.year], from: birthday, to: today)

        guard let age = dateComponents.year, age >= 0 else {
            return nil
        }

        self.name = name
        self.age = age
    }
}

let john = Person(name: "John" , age: 18) // error: extra argument 'age' in call
let paul = Person(name: "Paul", birthday: someBirthday) // ok

解決方法

この問題はイニシャライザをextensionで追加すると解決します。
下の例ではbirthday:を引数に取る新しいイニシャライザはもちろんですが、デフォルトのMemberwise Initializerも使えるようになっています。

struct Person {
    let name: String
    let age: Int
}

extension Person {
    init?(name: String, birthday: Date) {
        let today = Date()
        let dateComponents = Calendar.current.dateComponents([.year], from: birthday, to: today)

        guard let age = dateComponents.year, age >= 0 else {
            return nil
        }

        self.name = name
        self.age = age
    }
}

let john = Person(name: "John", age: 18) // ok
let paul = Person(name: "Paul", birthday: someBirthday) // ok

良いですね 👍

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1