>100 Views
March 06, 17
スライド概要
Swift のイニシャライザーの基礎的なところについて 30 分くらいで復習するのに使った資料です。2017/03/06 の『AKIBA.swift × Swift愛好会 vol2』で発表しました。
※ Docswell での公開に移行する直前の Slideshare での閲覧数は 2,197 でした。
正統派趣味人プログラマー。プログラミングとは幼馴染です。
ΠχγϟϥΠβʔ ෮शձ !",*#"TXJGUº4XJGUѪձWPM ۽୩༑ IUUQF[OFUKQ 4XJGU TXJGUQN
۽୩༑ 5PNPIJSP,VNBHBJ ⾣ 4XJGU͕ޠݴେ͖Ͱ͢ʂ ⾣ ΈΜͳͰָ͠Ήษڧձ͕େ͖Ͱ͢ʂ ⾣ ϓϩάϥϛϯάͷָ͠͞Λ͍͖͍͑ͯͨɻ !FT@LVNBHBJ UPNPIJSPLVNBHBJ $PEF1JFDFGPSNBD04 IUUQF[OFUKQ 9DPEFపఈղઆ
ษڧձΛ։࠵͍ͯ͠·͢ɻ Θ͍Θ͍ɺָ͘͠ɺ ΈΜͳͰޠΒ͑ΔॴΛࢦͯ͠ ԣJ1IPOF։ൃऀษڧձ ୈճΛ݄ʹ։࠵ʢඪʣ ΧδϡΞϧ4XJGUษڧձ ZJEFW ˏԣɾഅंಓ IUUQTBUOEPSHHSPVQTZJEFW ୈճݕ౼த DTXJGU !ԣɾ੨༿ IUUQTBUOEPSHHSPVQTDTXJGU ΈΜͳͰ4XJGU ෮शձ NJOOB@EF@TXJGU ˏौ୩ ୈճΛ݄ʹ։࠵༧ఆ IUUQDTXJGUDPOOQBTTDPN
NPPLNPPLSBEJP ϜοΫϜοΫϥδΦ ۽୩ͱ៸໘͕ϓϩάϥϛϯάίʔυͷ͔Β ௌ͑ͯ͘͜ΔʹࣖΛָ͚ͯ͠ΉϥδΦ ຖ݄ୈ̎ɾୈ̐ ݄༵ ʹ৴ IUUQNPPLNPPLSBEJPDPNB ⾣ ୈ ʰNFUIPEEJTQBUDIʱ ⾣ ୈ ʰάϩʔόϧมʱ ⾣ ୈ ʰHFUUFSͱTFUUFSʱ ⾣ ୈ ʰܕΤΠϦΞεʹ͍ΛͤΔʱ ⾣ ୈ ̕ ʰVOTBGF#JU$BTUΛͭݟΊͯΈ͍ͨʱ ⾣ ୈ ̔ ʰ໊લۭؒͷ͕ௌ͖͍ͨʱ
ΠχγϟϥΠβʔ
Πϯελϯεͷੜ جຊॻࣜ ࣮ͷجຊ
Πϯελϯεͷੜ جຊॻࣜ ⾣ ʹܕJOJUͰఆٛ͢Δ ⾣ ҾϦετΛఴ͑ɺΓࢦఆ͠ͳ͍ struct Person { init(name: String, number: Int) { } }
Πϯελϯεͷੜ ࣮ͷجຊ ⾣ શͯͷอଘܕϓϩύςΟʔΛॳظԽ͢Δ ⾣ ͻͱͭͰॳظԽ͠ͳ͍ͱίϯύΠϧΤϥʔ struct Person { var name: String var number: Int init(name: String, number: Int) { self.name = name } } SFUVSOGSPNJOJUJBMJ[FSXJUIPVUJOJUJBMJ[JOHBMMTUPSFEQSPQFSUJFT
ੜͰ͖ͳ͍͜ͱΛߟྀ ࣦഊͨ͠ΒͲ͏͠Α͏ͳ͍ͱ͖ ࣦഊ͢Δ͔͠Εͳ͍ͱ͖ ࣦഊͷৄࡉΛ௨͍ͨ͠ͱ͖
ੜͰ͖ͳ͍͜ͱΛߟྀ ࣦഊͨ͠ΒͲ͏͠Α͏ͳ͍ͱ͖ ⾣ ௨ৗ௨ΓJOJUͰ࣮͢Δ ⾣ ࣦഊGBUBM&SSPSͰ௨͢Δ struct Person { init(name: String, number: Int) { guard name.isVaidAsPersionName() else { fatalError("Invalid name") } :
ੜͰ͖ͳ͍͜ͱΛߟྀ ࣦഊ͢Δ͔͠Εͳ͍ͱ͖ ⾣ init?·ͨinit!Ͱ࣮͢Δ ⾣ ࣦഊͨ͠ΒnilΛฦ͢ struct Person { init?(name: String, number: Int) { guard name.isVaidAsPersionName() else { return nil } :
ੜͰ͖ͳ͍͜ͱΛߟྀ ࣦഊͷৄࡉΛ௨͍ͨ͠ͱ͖ ⾣ init … throwsͰ࣮͢Δ ⾣ ࣦഊͨ͠Β&SSPSΛฦ͢ struct Person { init(name: String, number: Int) throws { guard name.isVaidAsPersionName() else { throw InitializeError.invalidName } :
ੜͰ͖ͳ͍͜ͱΛߟྀ ະॳظԽͰࣦഊͰ͖Δ ⾣ ϓϩύςΟʔΛॳظԽͯ͠ͳࣦͯ͘ഊͰ͖Δ ⾣ ҎલॳظԽΛࡁ·ͤͳ͍ͱ͍͚ͳ͍߹͕͋ͬͨ class Person { var name: String var number: Int init?(name: String, number: Int) { guard name.isVaidAsPersionName() else { return nil } อଘܕϓϩύςΟʔͷॳظԽલͰࣦഊՄೳ
ΠχγϟϥΠβʔͷ໋໊نଇ ϥϕϧ͚ͷجຊ อଘͷܕมͰͷ໋໊نଇ 7BMVF1SFTFSWJOH5ZQF$POWFSTJPO ղऍΛ͏ܕมͰͷ໋໊نଇ /BSSPXJOH5ZQF$POWFSTJPO
ΠχγϟϥΠβʔͷ໋໊نଇ ϥϕϧ͚ͷجຊ ⾣ Ҿຖʹ୶ʑͱϥϕϧΛ͚ͭΔ ⾣ ӳจͱͯ͠ͷྲྀΕҙࣝ͠ͳͯ͘ྑ͍ struct Person { init(name: String, number: Int) { } ӳจͷྲྀΕҙࣝ͠ͳͯ͘ྑ͍ init(havingName: String, andNumber: Int) { } ͜Μͳ෩ʹؤுΒͳͯ͘ྑ͍
ΠχγϟϥΠβʔͷ໋໊نଇ อଘͷܕมͰͷ໋໊نଇ ⾣ 4XJGUͰΠχγϟϥΠβʔͰܕมΛߦ͏ ⾣ ׳शͱͯ͠ɺ࠷ॳͷҾʹϥϕϧΛ͚ͭͳ͍ struct Number { init( _ string: String, radix: Int) { *OU͔Β/VNCFSͷ7BMVF1SFTFSWJOH5ZQF$POWFSTJPOΛදݱ }
ΠχγϟϥΠβʔͷ໋໊نଇ ղऍΛ͏ܕมͰͷ໋໊نଇ ⾣ ͞·͟·ͳղऍΛ͏ܕม ⾣ มํ๏Λ࠷ॳͷϥϕϧͰઆ໌͢Δ struct WebSite { init(url: String, baseAddress: URL? = nil) { 63-͔ΒॳظԽ͢Δ/BSSPXJOH5ZQF$POWFSTJPOΛදݱ }
ʹܕΑͬͯมΘΔੑ֨ ܕͷΠχγϟϥΠβʔ ࢀরܕͷΠχγϟϥΠβʔ
ʹܕΑͬͯมΘΔੑ֨ ܕͷΠχγϟϥΠβʔ ⾣ ܕσʔλߏΛද͢ݱΔ ⾣ σʔλྖҬΛॳظԽ͢Δͷ͕త ΠχγϟϥΠβʔ *OJUJBMJ[FS ϝϯόʔϫΠζΠχγϟϥΠβʔ .FNCFSXJTF*OJUJBMJ[FS
ʹܕΑͬͯมΘΔੑ֨ʢܕʣ ΠχγϟϥΠβʔ ⾣ σʔλͷॳظΛܾఆ͢ΔΠχγϟϥΠβʔ ⾣ อଘܕϓϩύςΟʔશͯʹΛઃఆ͢Δ struct Person { var name: String var number: Int init(name: String) { self.name = name self.number = getNextNumber() }
ʹܕΑͬͯมΘΔੑ֨ʢܕʣ .FNCFSXJTFΠχγϟϥΠβʔ ⾣ શͯͷอଘܕϓϩύςΟʔΛड͚औͬͯॳظԽ ⾣ ܕຊମʹJOJU࣮Λলུ͢Δͱࣗಈ࣮͞ΕΔ struct Person { var name: String var number: Int } // イニシャライザーを定義しなくても使える let someone = Person(name: "Kumagai", number: 2)
ʹܕΑͬͯมΘΔੑ֨ʢܕʣ ͰܕΠχγϟϥΠβʔΛ֦ு ⾣ FYUFOTJPOͰΠχγϟϥΠβʔΛ֦ுͰ͖Δ ⾣ ΛॳظԽͨ͠ΓɺผͷJOJUΛݺΜͩΓͰ͖Δ struct Person { var name: String var number: Int } extension Person { init(name: String) { self.init(name: name, number: getNextNumber()) }
ʹܕΑͬͯมΘΔੑ֨ ࢀরܕͷΠχγϟϥΠβʔ ⾣ ࢀরܕɺঢ়ଶΛڞ༗ཧ͢ΔΦϒδΣΫτ ⾣ JOJUͷతʹɺΦϒδΣΫτ੍ޚͷ؍ՃΘΔ ࢦఆΠχγϟϥΠβʔ %FTJHOBUFE*OJUJBMJ[FS ศٓΠχγϟϥΠβʔ $POWFOJFODF*OJUJBMJ[FS ඞਢΠχγϟϥΠβʔ 3FRVJSFE*OJUJBMJ[FS
ʹܕΑͬͯมΘΔੑ֨ʢࢀরܕʣ ࢦఆΠχγϟϥΠβʔ ⾣ ॳظԽͷॏཁͳׂΛ୲͏ΠχγϟϥΠβʔ ⾣ ܧঝઌͰΦʔόʔϥΠυͰ͖Δ ⾣ ܧঝઌͰ৽ͨʹ࣮͢ΔͱɺͷJOJUΛӅṭ͢Δ w ΦʔόʔϥΠυ͚ͩͳΒͷଞJOJUӅṭ͠ͳ͍ class Base { init(name: String, number: Int) { } }
ʹܕΑͬͯมΘΔੑ֨ʢࢀরܕʣ ศٓΠχγϟϥΠβʔ ⾣ ࠷ޙଞͷࢦఆΠχγϟϥΠβʔͼݺग़͢ඞཁ͕͋Δ ⾣ ܧঝઌͰΦʔόʔϥΠυͰ͖ͳ͍ ⾣ ܧঝઌͰ৽ͨʹ࣮ͯ͠ɺͷJOJUΛӅṭ͠ͳ͍ class Base { convenience init(name: String) { self.init(name: name, number: getNextNumber()) } }
ʹܕΑͬͯมΘΔੑ֨ʢࢀরܕʣ ඞਢΠχγϟϥΠβʔ ⾣ ࢦఆΠχγϟϥΠβʔͱಉͷׂ ⾣ ܧঝઌͰΦʔόʔϥΠυ͠ͳ͚Ε͍͚ͳ͍ ⾣ Ӆṭ͞Εͳ͚ΕɺΦʔόʔϥΠυলུՄೳ class Base { required init(name: String, number: Int) { } }
ʹܕΑͬͯมΘΔੑ֨ʢࢀরܕʣ ࢀরܕͷ֦ுͰ͑Δͷ ⾣ ศٓΠχγϟϥΠβʔΛ֦ுͰ͖Δ ⾣ ࢦఆJOJUඞਢJOJU֦ுͰ͖ͳ͍ extension Object { convenience init(a: Int) { … } 0, init(b: Int) { … } EFTJHOBUFEJOJUJBMJ[FSNVTUCFEFDMBSFEEJSFDUMZJO required nit(c: Int) { … } SFRVJSFEJOJUJBMJ[FSNVTUCFEFDMBSFEEJSFDUMZJODMBTT
JOJUͷ֎ଆ͔ΒͷॳظԽ ϓϩύςΟʔʹطఆΛઃఆ طఆͰॳظԽ͢Δͱ͖ͷҙ .FNCFSXJTFJOJUͱطఆ
JOJUͷ֎͔ΒॳظԽͰ͖Δ ϓϩύςΟʔʹطఆΛઃఆ ⾣ อଘܕϓϩύςΟʔʹॳظΛࢦఆͰ͖Δ ⾣ JOJU͕ݺΕΔલʹઃఆ͞ΕΔ class View { var textColor = NSColor.black var backgroundColor = NSColor.white init() { } } JOJUͰॳظԽ͠ͳͯ͘0,
JOJUͷ֎͔ΒॳظԽͰ͖Δ طఆͰॳظԽ͢Δͱ͖ҙ ⾣ ݪଇɺͲΜͳ߹ͰॳظԽ͞ΕΔ ⾣ JOJUͰॳظԽ͢Δͱɺ̎ճॳظԽ͞ΕΔ class Object { var value = Value() JOJUલʹॳظԽ͞ΕΔ init() { value = Value() } } JOJUͰॳظԽ͢ΔͱɺॳظΛ্ॻ
JOJUͷ֎͔ΒॳظԽͰ͖Δ .FNCFSXJTFJOJUͱطఆ ⾣ .FNCFSXJTFJOJUطఆΛແࢹ͢Δ ⾣ ࣗͰಉͷJOJUΛ࡞ΔͱɺॳظԽ͕ॏෳ struct Data { var value = Value() } طఆ͕ઃఆ͞Ε͍ͯͯʜ let data = Data(value: Value()) ϝϯόʔϫΠζΠχγϟϥΠβʔͳΒطఆΘΕͳ͍
.FNCFSXJTFΠχγϟϥΠβʔ ࣗಈ࣮͞Εͳ͍ͱ͖ ࣗಈ࣮͞ΕΔͱ͖ ϓϩύςΟʔ͕طఆΛ࣋ͭͱ͖ QVCMJDʹఏ͖ͱ͍ͨ͠ڙʜ
.FNCFSXJTFΠχγϟϥΠβʔ ࣗಈ࣮͞Εͳ͍ͱ͖ ⾣ ܕຊମʹಠࣗʹJOJUΛ࣮ͨ͠ͱ͖ ⾣ ಠࣗʹ࣮ͨ͠ͷ͚͕ͩར༻Ͱ͖Δ struct Person { var name: String var number: Int init(name: String) { self.name = name self.number = getNextNumber() } }
.FNCFSXJTFΠχγϟϥΠβʔ ࣗಈ࣮͞ΕΔͱ͖ ⾣ ܕຊମʹJOJUΛ࣮͠ͳ͍ͱ͖ ⾣ ֦ܕுͰ࣮ͨ͠JOJUʹӨ͞ڹΕͳ͍ struct Person { var name: String var number: Int } extension Persion { init(name: String) { self.name = name self.number = getNextNumber() }
.FNCFSXJTFΠχγϟϥΠβʔ ϓϩύςΟʔ͕طఆΛ࣋ͭͱ͖ ⾣ શͯΛઃఆ͢Δ.FNCFSXJTFJOJU͕ఏ͞ڙΕΔ ⾣ શͯΛলུͨ͠߹ͷJOJUఏ͞ڙΕΔ struct RandomGenerator { var seed1: UInt32 = arc4random() var seed2: UInt32 = arc4random() } let gen1 = RandomGenerator() let gen2 = RandomGenerator(seed1: 0, seed2: 1)
.FNCFSXJTFΠχγϟϥΠβʔ .FNCFSXJTFJOJUͷΞΫηεൣғ ⾣ طఆͰJOUFSOBMΞΫηε ⾣ JOUFSOBMະຬͷϓϩύςΟʔΛ࣋ͭ߹ɺ ΞΫηεൣғ͍ͪΜ͍ͷʹἧ͑ΒΕΔ ⾣ ϓϩύςΟʔ͕શͯQVCMJDͰɺ .FNCFSXJTFΠχγϟϥΠβʔJOUFSOBM
.FNCFSXJTFΠχγϟϥΠβʔ QVCMJDʹఏ͖ͱ͍ͨ͠ڙʜ ಉͷJOJUΛಠࣗఆٛ͢ΔҊ ֦ܕுͰத͢ܧΔҊ
.FNCFSXJTFΠχγϟϥΠβʔ ಉͷJOJUͰQVCMJDఏ͢ڙΔҊ ⾣ ඪ४ͷ.FNCFSXJTFJOJUͱಉʹར༻Ͱ͖Δ ⾣ طఆ͖ͷϓϩύςΟʔॏෳॳظԽ͞ΕΔͷͰҙ public struct MyData { public var value = MyValue() public init(value: MyValue) { self.value = value } }
.FNCFSXJTFΠχγϟϥΠβʔ ֦ுJOJUͰQVCMJDఏ͢ڙΔҊ ⾣ ඪ४ͷ.FNCFSXJTFJOJUΛͦͷ··͏ ⾣ ॏෳॳظԽΛճආͰ͖Δ͕ɺϥϕϧিಥճආ͕ඞཁ public struct MyData { public var value = MyValue() } extension MyData { public init(memberwiseWithValue value: MyValue) { self.init(value: value) } }
.FNCFSXJTFΠχγϟϥΠβʔ Φεεϝ͍ͨ͠ଥڠҊ ⾣ ϓϩύςΟʔͷॳظԽΛΊΔ ⾣ .FNCFSXJTFJOJUಉͷJOJUΛಠ࣮ࣗ͢Δ public struct MyData { public var value: MyValue public init(value: MyValue) { self.value = value } }
ΠχγϟϥΠβʔͷͼݺग़͠ ʹ໊ܕҾΛ͢ํ๏ ܕJOJUΛ͏ํ๏
ΠχγϟϥΠβʔͷͼݺग़͠ ʹ໊ܕҾΛ͢ํ๏ ⾣ ʹ໊ܕҾϦετΛఴ͑ͯͼݺग़͢ ⾣ ֘͢ΔJOJU͕ͼݺग़͞ΕΔ let speaker = Person("Kumagai", 1234)
ΠχγϟϥΠβʔͷͼݺग़͠ ܕJOJUΛ͏ํ๏ ⾣ ʹ໊ܕJOJUΛ໌ͼݺͯ͠هग़͢ ⾣ ؔܕมʹ֨ೲͯ͑͠Δ let h = Person.init(name: "Kumagai", number: 1234) // 関数型変数 f にイニシャライザーを入れて使える let f: (String,Int) -> Person = Person.init(name:number:) let someone = f("Kumagai", 1234)
ΠχγϟϥΠβʔͷͼݺग़͠
ܕJOJUΛ͏ํ๏
⾣
ܕਪͰ͖Ͱ༻׆Δ
⾣
લ͔ޙΒਪͯ͠JOJUΛ͚ͯͭ͘ݟΕΔ
// 取り得る型から推論する
let list = MemberList(persons: .init(name: "A"))
// 関数内で、戻り値の型から推論する
func makePerson(name: String) -> Person {
return .init(name: name)
}
ϓϩτίϧͰJOJUΛنఆ ϓϩτίϧͰ࣮Λ͚ٛΔ
ϓϩτίϧͰJOJUΛنఆ ϓϩτίϧͰ࣮Λ͚ٛΔ ⾣ ϓϩτίϧʹJOJUΛنఆͰ͖Δ ⾣ نఆͨ͠JOJUɺඞਢΠχγϟϥΠβʔ૬ protocol ExpressibleByName { init(name: String) }
ϓϩτίϧͰJOJUΛنఆ ϓϩτίϧͰ࣮Λ͚ٛΔ ⾣ ܕɺී௨ʹJOJUͰద߹͢Δ ⾣ ࢀরܕɺSFRVJSFEJOJUͰద߹͢Δ // 値型をプロトコルに適合させるとき struct Person : ExpressibleByName { init(name: String) { … } } // 参照型をプロトコルに適合させるとき class Thread : ExpressibleByName { required init(name: String) { … } }
ϓϩτίϧͰJOJUΛنఆ Ϋϥε֦ுͰద߹Ͱ͖ͳ͍ ⾣ ϓϩτίϧ͕ٻΊΔJOJUSFRVJSFE૬ ⾣ ࢀরܕɺ֦ܕுͰϓϩτίϧʹద߹Ͱ͖ͳ͍ // 値型はプロトコルに適合できる extension Person : ExpressibleByName { init(name: String) { … } } // 参照型はプロトコルに適合できない extension Thread : ExpressibleByName { required init(name: String) { … } } SFRVJSFEJOJUJBMJ[FSNVTUCFEFDMBSFEEJSFDUMZJODMBTT
ϝλλΠϓͰॳظԽ͢Δ ܕͷΠχγϟϥΠβʔΛϝλλΠϓ͔Β͏ ࢀরܕͷΠχγϟϥΠβʔΛϝλλΠϓ͔Β͏
ϝλλΠϓͰॳظԽ͢Δ ܕͷJOJUΛϝλλΠϓ͔Β͏ ⾣ ܕͷϝλλΠϓ型.selfͰऔΓग़ͤΔ ⾣ ϝλλΠϓ͔ΒinitΛͼݺग़ͤΔ struct Value { init() { … } } // メタタイプ型の変数に保存して … let type: Value.Type = Value.self // そこからインスタンスを生成できる let instance: Value = type.init()
ϝλλΠϓͰॳظԽ͢Δ ࢀরܕͷJOJUΛϝλλΠϓ͔Β͏ ⾣ ࢀরܕSFRVJSFEJOJU͚͕ͩͼݺग़ͤΔ ⾣ ͦ͏Ͱͳ͍ͱɺܧঝઌͷJOJUͷଘࡏΛอূͰ͖ͳ͍ class Object { required init(a: Int) {} init(b: Int) {} } let type: Object.Type = Object.self let a = type.init(a: 0) let b = type.init(b: 0) 0, DPOTUSVDUJOHBOPCKFDUPGDMBTTUZQF0CKFDUXJUIBNFUBUZQF WBMVFNVTUVTFBSFRVJSFEJOJUJBMJ[FS
ϝλλΠϓͰॳظԽ͢Δ ϙϦϞʔϑΟζϜߟྀ͞ΕΔ ⾣ جఈͷϝλλΠϓʹɺੜઌͷΛೖΕΒΕΔ ⾣ ܧঝؔΛߟྀͯ͠JOJU͕ݺΕΔ class Base { required init() { … } } class Sub : Base { required init() { … } } let types = [Base.self, Sub.self] as [Base.Type] let instances = types.map { $0.init() }
࠷ʹޙએ
!ौ୩DBGF "QQMF5IF4XJGU1SPHSBNNJOH-BOHVBHFΛࢀߟʹ 4XJGUͷখ͞ͳࣄฑΛ͍ࢹͰோΊͯΈΔձ ࠓճͷൃදΈ͍ͨͳΛ࣌ؒ͘Β͍͔͚ͯ ΈΜͳͱΘ͍Θ͍ஊসͯ͠·͢ʂ IUUQTDTXJGUDPOOQBTTDPN NJOOB@EF@TXJGU
&OKPZ4XJGU 5IBOLZPV ΠχγϟϥΠβʔ෮शձ ۽୩༑ !FT@LVNBHBJ ⾣ ֓ཁ ⾣ ໋໊نଇ ⾣ ʹܕΑͬͯมΘΔੑ֨ ⾣ ͼݺग़͠ ⾣ JOJU֎͔ΒͷॳظԽ ⾣ .FNCFSXJTFΠχγϟϥΠβʔ ⾣ ϓϩτίϧͰJOJUΛنఆ ⾣ ϝλλΠϓ͔ΒॳظԽ͢Δ