Last active
April 5, 2023 21:28
-
-
Save niwatako/4011c9f77019e38b85e3 to your computer and use it in GitHub Desktop.
【続編】もしも `extension PROTOCOL where Self: T` を親子のクラスにそれぞれ適用したら採用される実装はどっち #CodePiece
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // A とそのサブクラス B が、"プロパティnameを持つ" SomeProtocolに準拠することを宣言。 | |
| class A {} | |
| class B: A {} | |
| protocol SomeProtocol { var name: String { get } } | |
| extension A: SomeProtocol {} | |
| // Aにnameのデフォルト実装を用意 | |
| extension SomeProtocol where Self: A { | |
| var name: String { return "My name is A" } | |
| } | |
| // BはAを継承していますが、更にデフォルト実装を上書きします | |
| extension SomeProtocol where Self: B { | |
| var name: String { return "My name is B" } | |
| } | |
| // この状態では、それぞれ異なる name の実装が機能します | |
| A().name // My name is A | |
| B().name // My name is B | |
| // ところが、インスタンスのプロパティとして格納された途端に... | |
| class C { | |
| var person: SomeProtocol | |
| init(_ person: SomeProtocol) { self.person = person } | |
| } | |
| let cA = C(A()) | |
| let cB = C(B()) | |
| // Bの name は スーパークラス A のデフォルト実装が実行されるようになりました! | |
| cA.person.name // My name is A | |
| cB.person.name // My name is A | |
| // ただし、Genericsを使うと | |
| class D<T: SomeProtocol>: SomeProtocol { | |
| var person: T | |
| init(_ person: T) { self.person = person } | |
| var name: String { return person.name } | |
| } | |
| // A、Bそれぞれのデフォルト実装が採用されました! | |
| let dA = D<A>(A()) | |
| let dB = D<B>(B()) | |
| dA.person.name // My name is A | |
| dB.person.name // My name is B | |
| /* | |
| では Generics を使ったオブジェクトが、 | |
| 再びGenericsを使っていないインスタンスに格納されると... | |
| ※もう一度 class C を利用してみます | |
| */ | |
| //class C { | |
| // var person: SomeProtocol | |
| // init(_ person: SomeProtocol) { self.person = person } | |
| //} | |
| let cA2 = C(dA) | |
| let cB2 = C(dB) | |
| cA2.person.name // My name is A | |
| cB2.person.name // My name is A | |
| /** | |
| `extension PROTOCOL where Self: T` が親子に定義された時、 | |
| 型情報Tが保持された文脈では、Tにextensionしたものが実行されるが、 | |
| PLOTOCOL の情報のみの文脈になると、 | |
| 親クラスに extension されたものが実行される(と思われる) | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment