Swiftの基本 イニシャライザ、パート1

1.イニシャライザの基本

まずストアドプロパティtoとコンピューテドプロパティbodyを持つ構造体Greetを定義します。(sample1)

sample1

struct Greet{
    let to:String
    var body:String{
        return "Hello,\(to)!!!!!"
    }
    
    init(to:String){  //←がイニシャライザ
        self.to=to
    }
}

init(引数){初期化処理}

の部分がイニシャライザの定義。

次に構造体Greetのインスタンスを生成します。(sample2)

sample2

struct Greet{
    let to:String
    var body:String{
        return "Hello,\(to)!!!!!"
    }
    
    init(to:String){
        self.to=to
    }
}

let gr1=Greet(to:"address1")  //インスタンス生成。この時自動的に
                              //イニシャライザが実行される。

print(gr1.body)
Hello,address1!!!!!

Greet型のインスタンス生成時に、引数toに文字列”address1″が渡されてイニシャライザが呼び出されます。コンピューテドプロパティbodyにアクセスすると、イニシャライザにより初期化されたストアドプロパティtoを参照して文字列

Hello,address1!!!!!

を返します。

ためしに引数無しでGreet型のインスタンスを生成してみると、(sample3)

sample3

struct Greet{
    let to:String
    var body:String{
        return "Hello,\(to)!!!!!"
    }
    
    init(to:String){
        self.to=to
    }
}

let gr1=Greet()
//コンパイルエラー
main.swift:13:15: error: missing argument for parameter 'to' in call
let gr1=Greet()
              ^
              to: <#String#>
main.swift:8:5: note: 'init(to:)' declared here
    init(to:String){

コンパイルエラーになります。イニシャライザ呼び出し時(インスタンス生成時)に引数toが必要なのに渡されていない」ということですね。

もうひとつ試しにイニシャライザの引数に数値をセットしてインスタンスを生成を試みます。(sample4)

sample4

struct Greet{
    let to:String
    var body:String{
        return "Hello,\(to)!!!!!"
    }
    
    init(to:String){
        self.to=to
    }
}

let gr1=Greet(to:345)
main.swift:13:18: error: cannot convert value of type 'Int' to expected argument type 'String'
let gr1=Greet(to:345)
                 ^~~

コンパイルエラーです。「渡されたInt型の値345をString型に型変換できない」と言ってますね。

インスタンスの全てのプロパティは、インスタンス化完了までに初期化されている(値がセットされている)必要があります。イニシャライザに適切な型を指定してプロパティの初期化処理を記述しておけば、「プロパティの初期化が正しい型の値によりもれなく行われているか」をコンパイラが自動的にチェックしてくれる、ということですね。


また別の試みとして、新しいプロパティpropを付け加えてみます。(sample5)

sample5

struct Greet{
    let to:String
    let prop:String  //←ストアドプロパティpropを追加
    var body:String{
        return "Hello,\(to)!!!!!"
    }
    
    init(to:String){ //イニシャライザはそのまま
        self.to=to
    }
}

let gr1=Greet(to:"address1")
//コンパイルエラー
main.swift:11:5: error: return from initializer without initializing all stored properties
    }
    ^
main.swift:4:9: note: 'self.prop' not initialized
    let prop:String

Greet型の定義にプロパティpropを加えましたので、プロパティは

to

prop

の二つになりました。しかしイニシャライザは変更していないので、toの初期化しかできない状態ですね。結果はコンパイルエラーです。

「すべてのストアドプロパティを初期化するイニシャライザが必要」という警告ですね。ですのでエラーが出なくするには、sample6のように構造体定義時に初期値をセットする(sample6)

sample6

struct Greet{
    let to:String
    let prop:String="prop"  //←ここでpropプロパティを初期化
    var body:String{
        return "Hello,\(to)!!!!!\nprop is'\(prop)'"
    }
    
    init(to:String){   //←toプロパティはイニシャライザで初期化
        self.to=to
    }
}

let gr1=Greet(to:"address1")
print(gr1.body)
Hello,address1!!!!!
prop is'prop'

あるいは、イニシャライザでpropプロパティも初期化するように変更する(sample7)

sample7

struct Greet{
    let to:String
    let prop:String
    var body:String{
        return "Hello,\(to)!!!!!\nprop is'\(prop)'"
    }
    //↓すべてのストアドプロパティが初期化されるようにイニシャライザを修正
    init(to:String,prop:String){
        self.to=to
        self.prop=prop
    }
}

let gr1=Greet(to:"address1",prop:"prop2")
print(gr1.body)
Hello,address1!!!!!
prop is'prop2'

 

コメントを残す

メールアドレスが公開されることはありません。