post Image
extension where T: SomeClass と where T == SomeClass の補完上の区別 & 原因求む

TL;DR

下記の図をご覧ください
スクリーンショット 2017-11-07 23.52.16.png
.
スクリーンショット 2017-11-07 23.52.31.png

そうです、: を使った場合、制約が満たされてなかったら補完リストに出ませんが、== を使う時は制約が満たされてなくても補完リストに出ます(当然コンパイルエラーにはなりますが)。理由は不明。エロい人教えてください。

細かい話

拡張は Swift で非常に頻繁に使われる機能の一つですが、特定な状況を拡張したい、例えば ArrayElementString であるのみの時に使われる joined(separator: String) -> String 機能はこんな感じで定義されています:

extension Array where Element == String {
    public func joined(separator: String = default) -> String
}

このように、Swift では extension の後ろに where A == B と言うように制約をつけることができますが、where の書き方はここでは == を使いましたが、他に : を使うこともできます。同じように見えますが、意味として微妙に違います。== の場合は 「B である」ことを意味しますが、: の場合は「B と見なせる」場合を意味します。

そして、実はどんな状況でも両方使えるわけではありません、== のみ使える場合と、: のみ使える場合があります。具体的にはこんな感じです

B の型 == :
class ⭕️ ⭕️
struct ⭕️
protocol ⭕️

ご覧のように、==: が両方使えるのは Bclass のみの時です。なぜかと言うとまさに上記のニュアンスの違いがあって、Bclass の場合は「その class である」場合と、「その class のサブクラスである」時の区別がありますが、struct は継承の概念がないので「その struct である」場合だけしかないですし、逆に protocol の場合は protocol 自体は何か特定な型ではないので何かしらの型に落とし込む必要があるため、「その protocol である」ことは意味がないのです。

ちなみに、両方使える class の場合は上記通り、== を使う場合と : を使う場合は微妙に動きが違う時があります。それは protocol に対する extension で、ASelf の時:

PatternA
protocol Some {}
extension UIView: Some {}
extension Some where Self: UIView {
    func test() { print("works") }
}

UIView().test() //works
UIImageView().test() //works
PatternB
protocol Some {}
extension UIView: Some {}
extension Some where Self == UIView {
    func test() { print("test") }
}

UIView().test() //works
UIImageView().test() //error: 'UIImageView' is not convertible to 'UIView'

こうなる理由はとてもわかりやすいですね、==である を意味します。そして UIImageViewUIView を継承しているであって UIView ではないのです。だから : を使うと test() は普通に通りますが == を使うと test() がエラーになります

ところが、extension Array where Element == SomeClass の場合は、なぜか SomeClass のサブクラスでも通ります。ちょっと不思議な気分です🤔

でもこれも気になるのですが、今日一番気になるのはやはり TL;DR に書いてある補完の問題ですね。なぜか : で書くとちゃんと補完は正しいものにしか出てこないのですが == で書くと適合していない場合でも補完に出ます。コンパイルエラーになるのに。

ちなみに、なぜこの挙動に気づいたかと言うと、自分で NotAutoLayout という Auto Layout を殺す脱 Auto Layout のフレームワークを作っているのですが、中にこのように LayoutMaker という型を作って、Phantom Type っぽい挙動で特定な場合には特定なヘルパーメソッドを作りたかったのですが、なぜか補完リストには条件が合わない時のメソッドもズラッと出てきて、非常に不親切だなぁと思ってそうならないように結局渋々すごいたくさんの XxxLayoutMaker 型を作りました。ところで今日 Phantom Type についてこに記事を読んで、「あーでも .shout() は最初から補完リストに出るんだよなぁ」と思いながら Playground にソースコードコピペしたら出てこなかった!「ん?」って思って色々試してみた結果、その記事では : を使っているから補完リストが正しく動いたことが判明しました。

しかし、上の表にも書いてある通り、struct を使った場合はそもそも : が使えないので、class を使う必要があるんですよね…ところが class を作った場合、仮に final をつけたとしても、生成コストは struct より高いのであんまり使いたくない感 is ある…無限に protocol 生やすしかないのかな(白目


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。