AnyObject – 自分が見落としていた、基本の話

144 Views

October 16, 16

スライド概要

Swift の AnyObject の性質を、自分はすっかり見落としていたので、それについての基本的なところを確かめておくことにしました。Swift の @objc による動的ディスパッチ、けっこういい感じに出来たんですね。

※ Docswell での公開に移行する直前の Slideshare での閲覧数は 4,105 でした。

profile-image

正統派趣味人プログラマー。プログラミングとは幼馴染です。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

"OZ0CKFDU ࣗ෼͕‫ݟ‬མͱ͍ͯͨ͠ɺ‫ج‬ຊͷ࿩ ΧδϡΞϧ4XJGUษ‫ڧ‬ձ PO &;/&5‫۽‬୩༑޺ IUUQF[OFUKQ 4XJGU

2.

‫۽‬୩༑޺ 5PNPIJSP,VNBHBJ ⾣ 4XJGU‫͕ޠݴ‬௒େ޷͖Ͱ͢ʂ ⾣ ΈΜͳͰָ͠Ήษ‫ڧ‬ձ͕େ޷͖Ͱ͢ʂ ⾣ ϓϩάϥϛϯάͷָ͠͞Λ఻͍͖͍͑ͯͨɻ !FT@LVNBHBJ UPNPIJSPLVNBHBJ $PEF1JFDFGPSNBD04 IUUQF[OFUKQ 9DPEFపఈղઆ

3.

$PEF1JFDFGPSNBD04 ษ‫ڧ‬ձΛָ͠ΉΞϓϦ ⾣ ιʔείʔυΛ5XJUUFSͱ(JTUʹಉ࣌౤ߘ ⾣ ίʔυཝΛۭʹ͢Ε͹ɺී௨ʹπΠʔτՄೳ ⾣ ϋογϡλάΛઃఆͰ͖Δʗ෇͚๨Εͳ͍ #cswift

4.

ษ‫ڧ‬ձΛ։࠵͍ͯ͠·͢ɻ Θ͍Θ͍ɺָ͘͠ɺ ΈΜͳͰ‫ޠ‬Β͑Δ৔ॴΛ໨ࢦͯ͠ ԣ඿J1IPOF։ൃऀษ‫ڧ‬ձ ୈճ໨͸݄೔ͷ։࠵ ΧδϡΞϧ4XJGUษ‫ڧ‬ձ ୈճ໨Λ݄ʹ։࠵ʢ‫ݕ‬౼தʣ ΈΜͳͰ4XJGU ෮शձ ୈճ໨Λ݄தʹ։࠵ʢ‫ݕ‬౼தʣ ZJEFW ˏԣ඿ɾഅंಓ IUUQTBUOEPSHHSPVQTZJEFW DTXJGU !ԣ඿ɾ੨༿୆ IUUQTBUOEPSHHSPVQTDTXJGU NJOOB@EF@TXJGU ˏौ୩ IUUQDTXJGUDPOOQBTTDPN

5.

NPPLNPPLSBEJP Ќ൛ ϜοΫϜοΫϥδΦ ‫۽‬୩ͱ៸໘͕ϓϩάϥϛϯάίʔυͷ಺͔Β ௌ͑ͯ͘͜Δ੠ʹࣖΛ܏ָ͚ͯ͠ΉϥδΦ ຖ݄ୈ̎ɾୈ̐ ݄༵೔ ʹ഑৴ IUUQNPPLNPPLSBEJPDPNB ⾣ ୈ̑࿩ ʢ݄೔ʹ഑৴༧ఆʣ ⾣ ୈ̐࿩ ʰίϝϯτͷଓ͖ˍ੔਺‫ܕ‬ʱ ⾣ ୈ̏࿩ ʰίϝϯτʱ ⾣ ୈ̎࿩ ʰྻ‫ܕڍ‬ʱ ⾣ ୈ̍࿩ ʰϓϩάϥϛϯάͱࢲͨͪʱ

6.

ొஃͤͯ͞௖͚Δ͜ͱʹͳΓ·ͨ͠ɻ IUUQTFWFOUEPUTKQFWFOU

7.

"OZ0CKFDU

8.

ͦ͏͍͑͹"OZ0CKFDUͬͯɺ શͯͷΫϥε͕४‫͢ڌ‬Δϓϩτίϧ ʜͩͱ͚ͩɺࢥ͍ͬͯͨɻ

9.

४උ஌ࣝ r4XJGUr

10.

४උ஌ࣝ ෆಛఆ‫ܕ‬ "OZ ⾣ ೚ҙͷ‫ܕ‬ͷΠϯελϯεΛද‫͖Ͱݱ‬Δ ⾣ ೚ҙͷؔ਺‫ܕ‬΋‫·ؚ‬ΕΔ "OZ0CKFDU ⾣ ೚ҙͷΫϥε‫ܕ‬ͷΠϯελϯεΛද‫͖Ͱݱ‬Δ ⾣ ؔ਺‫ܕ‬͸!DPOWFOTJPO CMPDL ͳΫϩʔδϟʔΛ VOTBGF#JU$BTUͰΩϟετͨ͠৔߹͚ͩʹରԠ

11.

४උ஌ࣝ ෆಛఆ‫ܕ‬ͷఆٛ "OZ ⾣ ૊ΈࠐΈͷΩʔϫʔυͱͯ͠ఆٛ ⾣ 4XJGUͰ͸UZQFBMJBT"OZQSPUPDPMͰఆٛ "OZ0CKFDU ⾣ !PCKDQSPUPDPM"OZ0CKFDUͱͯ͠ఆٛ

12.

४උ஌ࣝ ෆಛఆ‫ܕ‬ͷ࢖༻ ⾣ ద੾ͳ‫ʹܕ‬Ωϟετͯ͠࢖͏ w JTԋࢉࢠɺBT BT ԋࢉࢠ w TXJUDIύλʔϯϚον switch instance { case 0 as Double: print("0 of Double") case let value as Int: print("\(value) of Int") case is Double: print("Double") }

13.

४උ஌ࣝ r0CKFDUJWF$r

14.

४උ஌ࣝ 0CKFDUJWF$Ϋϥε ⾣ .FTTBHF1BTTJOHํࣜ w ಈతσΟεύον ⾣ /40CKFDUΫϥεΛඞͣ‫ܧ‬ঝ w QFSGPSN4FMFDUPS‫ܥ‬ϝιουৗඋ

15.

"OZ0CKFDUͷ0CKFDUJWF$Ϋϥεͬͯɺ ࠷௿Ͱ΋/40CKFDUʹͯ͠QFSGPSN4FMFDUPS ʜ͢Δͷͩͱࢥ͍ͬͯͨɻ

16.

%ZOBNJD%JTQBUDI r"OZ0CKFDUr

17.

%ZOBNJD%JTQBUDI ֓ཁ ⾣ "OZ0CKFDU͸ಈతσΟεύονΛαϙʔτ ⾣ !PCKDࢦఆͷ‫ػ‬ೳΛ࣮ߦͰ͖Δ let object = "Casual" as AnyObject let count: Int? = object.length let _: Void? = object.append?("Swift")

18.

%ZOBNJD%JTQBUDI ϝιουͷ࣮ߦ ⾣ ௨ৗͱಉ͡ํ๏Ͱ࣮ߦ ⾣ σΟεύονՄೳ͔Ͳ͏͔Λ൑ఆՄೳ // 通常通りに実行可能(メソッドは IUO 属性付き) let result: String = object.appending("Swift") // 通常は、メソッドに応じられない場合は強制終了 let result: String = object.appending("Swift") &YFDVUJPOXBTJOUFSSVQUFE SFBTPO&9$@#"%@*/4536$5*0/ // メソッドに ? をつけて、ディスパッチ可能性も判定 let result: String? = object.appending?("Swift")

19.

%ZOBNJD%JTQBUDI ϓϩύςΟʔͷ࣮ߦ ⾣ ௨ৗͱಉ͡ํ๏Ͱ࣮ߦɺ஋͸0QUJPOBM‫ܕ‬ ⾣ σΟεύονͰ͖ͳ͚Ε͹OJM͕ฦΔ // 通常通りに実行可能、ただし戻り値は Optional 型 let count: Int? = object.length

20.

%ZOBNJD%JTQBUDI rཹҙ఺r

21.
[beta]
%ZOBNJD%JTQBUDIͷཹҙ఺

‫ܕ‬͸"OZ0CKFDUΛ໌‫ه‬
⾣ ΠϯελϯεΛ"OZ0CKFDU‫Ͱܕ‬ѻ͏
⾣ /40CKFDU‫ͳܕ‬ΒQFSGPSNϝιου΋Մೳ

class MyClass : NSObject {
func myFunction(_ v: Int) -> Int {…}
}
let object = MyClass() as AnyObject
let result: Int? = object.myFunction?(10)

22.
[beta]
%ZOBNJD%JTQBUDIͷཹҙ఺

/40CKFDUͰѻ͏͜ͱ΋Մೳ
⾣ /40CKFDUͰѻ͑͹QFSGPSN͕࢖͑Δ
⾣ Ҿ਺΍໭Γ஋͸"OZ΍0CKFDUJWF$‫Ͱܥ‬ѻ͏

class MyClass : NSObject {
func myFunction(_ v: Any) -> NSNumber {…}
}
let object = MyClass() as NSObject
let result: Unmanaged<AnyObject>? =
object.perform(MyClass.myFunction(_:), with: 5)
let resultValue: Int? =
result?.takeRetainedValue().intValue

23.
[beta]
%ZOBNJD%JTQBUDIͷཹҙ఺

"OZ0CKFDU૬౰‫ʹܕ‬͸ඇରԠ
⾣ "OZ0CKFDUΛ‫ܧ‬ঝͨ͠ϓϩτίϧ‫Ͱܕ‬͸‫ࡌه‬ෆՄ

protocol MyClassProtocol : AnyObject {
}
class MyClass : NSObject, MyClassProtocol {
func myFunction(_ v: Int) -> Int {…}
}
let object = MyClass() as MyClassProtocol
let result: Int? = object.myFunction?(10)
WBMVFPGUZQF.Z$MBTT1SPUPDPMIBTOPNFNCFSNZ'VODUJPO

24.
[beta]
%ZOBNJD%JTQBUDIͷཹҙ఺

࣮ߦͰ͖Δͷ͸!PCKDͷΈ
⾣ !PCKDͰଘࡏ͠ͳ͍γάωνϟ͸ϏϧυΤϥʔ
⾣ ಉ໊ͷ!OPOPCKD‫ػ‬ೳ͸ɺ‫ͼݺ‬ग़͞Εͳ͍

class Object : NSObject {
func method1() -> Int {…}
@nonobjc func method2() -> Int {…}
}
let object = Object() as AnyObject
let result1 = object.method1?()
let result2 = object.method2?()

// .some(x)
// .none

25.

%ZOBNJD%JTQBUDIͷཹҙ఺ !PCKDͷࢦఆํ๏ ⾣ /40CKFDUΫϥεΛ‫ܧ‬ঝ͢Δํ๏ ⾣ ରԠͨ͘͠ͳ͍΋ͷʹ͸!OPOPCKDΛ෇༩ // 原則、動的ディスパッチが可能 class Object : NSObject { func method1() -> Int {…} // 動的ディスパッチしたくないものに @nonobjc を付与 @nonobjc func method2() -> Int {…} }

26.

%ZOBNJD%JTQBUDIͷཹҙ఺ !PCKDͷࢦఆํ๏ ⾣ 4XJGUΫϥεͷ‫ػ‬ೳ͝ͱʹ!PCKDΛ෇༩͢Δํ๏ ⾣ !PCKDΛ෇͚ͳ͍΋ͷ͸ಈతσΟεύονෆՄ // 原則、動的ディスパッチは不可 class Object { func method1() -> Int {…} // 動的ディスパッチしたいものに @objc を付与 @objc func method2() -> Int {…} }

27.

%ZOBNJD%JTQBUDIͷཹҙ఺ !PCKDͷࢦఆํ๏ ⾣ ϓϩτίϧʹ!PCKDΛ෇༩͢Δํ๏ ⾣ ͦ͜Ͱ‫ن‬ఆ͞Εͨ΋ͷ͸ɺ҉໧తʹ!PCKDͰ࣮૷ @objc protocol Protocol { func method() } class Object : Protocol { func method() {} }

28.

%ZOBNJD%JTQBUDIͷཹҙ఺ γάωνϟʔͷ໊લʹ͍ͭͯ ⾣ γάωνϟʔ໊͸4XJGU໊Λࢦఆ͢Δʁ ⾣ 0CKFDUJWF$໊Ͱࢦఆͨ͠΋ͷ͸‫ݕ‬ग़͞Εͳ͍ class Object { @objc(otherName) func originalName() {} } let object = Object() as AnyObject object.originalName?() // .some(()) object.otherName?() WBMVFPGUZQF"OZ0CKFDUIBTOPNFNCFSPUIFS/BNF

29.

%ZOBNJD%JTQBUDIͷཹҙ఺ γάωνϟʔͷ໊લʹ͍ͭͯ ⾣ γάωνϟʔ໊͸0CKFDUJWF$໊΋ࢦఆͰ͖Δʁ ⾣ Ͳ͔͜ʹಉ໊ͷఆ͕ٛ͋Ε͹ɺ྆ํͰ࣮ߦՄೳʁ class OtherClass { @objc func otherName() {} } class Object { @objc(otherName) func originalName() {} } let object = Object() as AnyObject object.originalName?() object.otherName?() // .some(()) // .some(())

30.

%ZOBNJD%JTQBUDIͷཹҙ఺ γάωνϟʔͷ໊લʹ͍ͭͯ ⾣ 0CKFDUJWF$໊͕෇͍ͨ΋ͷͱࠞࡏ͢Δͱᐆດʁ class OtherClass { @objc func originalName() {} @objc func otherName() {} } class Object { @objc(otherName) func originalName() {} } let object = Object() as AnyObject object.originalName?() object.otherName?() // ambiguous use of … // .some(())

31.
[beta]
%ZOBNJD%JTQBUDIͷཹҙ఺

ఆٛ͞Ε͍ͯͳ͍‫ػ‬ೳ
⾣ Ͳ͔͜Ͱ!PCKD෇͖Ͱఆٛ͞Ε͍ͯΔඞཁ͋Γ
⾣ Ͳ͜ʹ΋ଘࡏ͠ͳ͍γάωνϟ͸ϏϧυΤϥʔ

class MyClass : NSObject {
func myFunction(_ v: Int) -> Int {…}
}
let object = MyClass() as AnyObject
let result: Int? = object.xxxx?(10)
WBMVFPGUZQF"OZ0CKFDUIBTOPNFNCFSYYYY

32.

%ZOBNJD%JTQBUDIͷཹҙ఺ ఆٛ৔ॴͷ஫ҙ ⾣ ϩʔΧϧείʔϓͷ!PCKDγάωνϟʔ͸ "OZ0CKFDUͷީิͱͯ͠ೝࣝ͞Εͳ͍ ⾣ Ͳ͔͜ʹಉ໊ͷ༗ޮͳγάωνϟʔ͕͋Ε͹ ϩʔΧϧείʔϓͷ!PCKD‫ػ‬ೳ͸࣮ߦͰ͖Δ func doSomething() { class Object: NSObject { // このシグネチャーは認識されない。動的実行は可 func someMethod() {} } }

33.

"OZ0CKFDU͕ ͜Μͳੑ࣭ͩͬͨͳΜͯɺ஌Βͳ͔ͬͨ ʜͦΜͳɺ͓࿩Ͱͨ͠ɻ

34.

&OKPZ4XJGU 5IBOLZPV "OZ0CKFDU ࣗ෼͕‫ݟ‬མͱ͍ͯͨ͠ɺ‫ج‬ຊͷ࿩ &;/&5‫۽‬୩༑޺ IUUQF[OFUKQ ⾣ ४උ஌ࣝ ⾣ ಈతσΟεύον