『プロトコル拡張を、それに準拠する将来の型で制約して、既定の実装を添えよう』という話を発端にした考察
- es_kumagai
- 1901
- 7
- 2
- 0
昨日の夜とは予想が若干違いましたけど、端的に言うと『型に実装を要求しないプロトコル拡張で Self の条件を「クラスでもプロトコルでも」何かで縛ると、すべてが既定の実装として採用される』ということになるように見えました。
2016-03-06 23:29:53検証してたらコメント入れて 600 行くらいのコードになったので、全部を CodePiece で投稿すると画像が見にくくなりそうなので、細切れにちょっとずつ連投してみます。
2016-03-06 23:33:52別で投稿したコード中の定義を使うみたいな場面もあるかもしれないので、試す時は注意してください。エラー箇所はコメントアウトしているので、全部をつなげれば正常に実行されるはず。
2016-03-06 23:33:57とりあえず定義。型に実装を要求するPと、それを使ったA->B->Cみたいなクラス。Pを拡張し、条件を「Self : どれかのクラス」にする。これは前提、深くは考えない。 gist.github.com/09d007ebe5994f… #swift pic.twitter.com/0YQCIgI0yt
2016-03-06 23:37:41課題としては『プロトコル P を起点に、それを継承したクラスで場合分けしてミックスインしたい』みたいな感じみたい。そして個人的に気になったのは、拡張条件をクラスで指定しているところ。それに注目して調べを進めてました。(最終的には、関係なさそうでしたが)
2016-03-06 23:39:56そしてちょっとクラスの性質チェック。既定クラスの配列ができます。これが関係しそう!と思ったものの、意味ないと論破され、そして実際、今回の件では意味がなかった。 gist.github.com/b1e1aa792d096a… #swift pic.twitter.com/XpNpACiOrd
2016-03-06 23:41:19プロトコル世界とオブジェクト世界の動きの違いの再確認。 gist.github.com/301d4a8f017834… #swift pic.twitter.com/OFvSpXSBpw
2016-03-06 23:42:17メソッドの実装のされ方の、こんな性質もあるよね、みたいな再確認。メソッドは型に静的メソッドとして添えられ、任意のインスタンスを添えて呼び出せます。 gist.github.com/6dcf61f134a7c0… #swift pic.twitter.com/PclMEsOqJt
2016-03-06 23:43:36これは、型に実装を要求する2つのプロトコルを用意して、親と子のそれぞれに適用、その場合どうなるか、みたいな検証。型 CC に限って衝突した、みたいなお話。 gist.github.com/b5ef7a9051076e… #swift pic.twitter.com/6zdFEvGlek
2016-03-06 23:47:47じゃあ、型に実装を要求するプロトコル2つを、親と子にずらすのではなく、ひとつのクラスに適用したらどうなるかの検証。 gist.github.com/05a1150db23ed3… #swift pic.twitter.com/IVGaCUYCZx
2016-03-06 23:49:12これは try! Swift の中で話にあった(型に実装を求める)プロトコル拡張が重複すると、実装先での主導実装を迫られる、のと同じことでした。
2016-03-06 23:50:10じゃあ、型への実装要求をやめてみたら?両方が実装されて衝突する話。 gist.github.com/5ebdb5d51dfcae… #swift pic.twitter.com/UB709RgRwL
2016-03-06 23:51:17これまで、基準になるプロトコルを継承するクラスで縛ってきたけど、関係ないクラスだとどうなるの?という話。衝突はしないが「型が違う」と言われた。メソッドの存在を知られてる? gist.github.com/9fee81a5a99ea2… #swift pic.twitter.com/4EbIQvvEWK
2016-03-06 23:53:46じゃあ、縁もゆかりもない2つの型で縛って拡張したら?…衝突した。どちらも採用されているようだ。 gist.github.com/c495772f0d4554… #swift pic.twitter.com/QHWsQaWdJc
2016-03-06 23:54:40ただ、別の書き方をしてみても、補完で候補が2つ出るようなことはなく、でも重複定義を匂わすエラーになりました。 gist.github.com/381a17e58d8438… #swift pic.twitter.com/DUwyCQ2LdB
2016-03-06 23:56:13どのクラスを指定しても実装が存在しそう。どのクラスでも、ってプロトコルで言う AnyObject じゃない?と思って検証したら、これでも衝突した。 gist.github.com/78bfaa9bb259a6… #swift pic.twitter.com/mKYzvDNlS9
2016-03-06 23:57:44クラスじゃないと同一視しないでくれるかな?と思って、クラスより低いプロトコルといえば Any なのでそれを指定したら、衝突しなかったけれど、これは別の理由みたい。 gist.github.com/fb39cfbe5b9cbf… #swift pic.twitter.com/lrkUtudkXp
2016-03-06 23:58:41ジェネリックの性質なのですけど " : Any" は指定していないのと同じ。プロトコル拡張も同様みたいで "where Self : Any" は無いのと同じ、つまり生粋の extension になるみたい。そしてそちらが優先されるみたい。ズバリ自分、だからと思っていいのかな?
2016-03-07 00:01:00もはや分からなくなってきたので、束縛条件でクラスではなく、縁もゆかりもないプロトコルを指定してみたら、衝突した。 gist.github.com/4a107361796bd7… #swift pic.twitter.com/sBzRrCzuad
2016-03-07 00:02:28つまり何でも、プロトコル拡張の条件縛りで "Self : " ならとりあえず、採用している可能性が強い。どうしてそういう動きになっているのか、その理由まではまだ見えない。けれど、とりあえず動き的なところは見えてきたし、この状況ならちょっと話は早そう。
2016-03-07 00:04:29というわけで、今のところの結論はこんな感じになりました。自分的にはひとまずこれで気が済んだような心地がしました。 gist.github.com/2df14730b7cace… #swift pic.twitter.com/gUNws8pIS0
2016-03-07 00:06:28先ほどの、読み返してみてちょっと長すぎたので、ひとつにまとめたコードをアップしておきました。 gist.github.com/EZ-NET/e367363…
2016-03-07 00:09:35