ジェネリクスとプロトコルなど [Swiftプログラミング]
個人的にちょっと困ったことが起きている。でも僕が何かして解決する内容ではないので、とりあえず頭を低くしてやり過ごすのを待つことにしてる。それですめばいいんだけど。
ところで全然話は違うけど、Swiftで書いててまたよくわからないことができた。こんどはジェネリクス....
たとえばこんな継承関係にあるプロトコル
ところがもちろん
全然別の話なんだけど他にも、ジェネリクスにスタティックなインスタンスを作ろうとすると
けっこうこういう、なんというか、機能が直交していないというか、細かいところでコンパイルできないことに出くわす。20年ほど前、Objective-Cを勉強し始めたころにこういう悩みはなかったような気がする。まあObjective-CはSwiftに比べると単純で、機能も限られている、ということかもしれないけど。
そういえばそのもっと昔、MPWでちまちま書くのをやめて、当時急速に流行りだしたCodeWarriorでPowerPlantを使うためにC++を勉強し始めたとき、C++の膨大さと複雑さに心が折れそうになった、というか結局心折れてしまってPlowerPlantとのインターフェイスだけC++で書いてあとはCで書いてた(というかC風の書き方でC++を書いてた。C++からCを呼ぶのは難しくないけどCからC++を呼ぶのは難しかった)。なんだかあれを思い出してしまう。
今考えるとPowerPlantもC++の機能のごく一部しか使ってなかったのに、全部を理解しようとして苦しんでいただけだったとは言える。もう25年以上前の話だけど、いまだにC++だけはまともに書けるとは思えない。多分もう死ぬまで書かないと思うけど。
どっちにしても実行時にクラッシュされるのに比べたらコンパイルできないことなんでむしろ喜ぶべきことで、もちろんSwiftの意図もそこにあるんだろうけど、Swiftで心折れたくないなあ。
ところで全然話は違うけど、Swiftで書いててまたよくわからないことができた。こんどはジェネリクス....
たとえばこんな継承関係にあるプロトコル
protocol Indispensable { var isValid: Bool { get } } protocol Transposable: Indispensable { }名前がへんなのは無視してもらって、これを型としてジェネリクスに使うことを考える。
struct Something<T: Indispensable> { }ところが
let obj = Something <Transposable>()と実体を作ろうとすると、
Value of protocol type 'Transposable' cannot conform to 'Indispensable'; only struct/enum/class types can conform to protocolsとプロトコルとしてconformしていても、コンパイラに怒られる。プロトコルが型として使えないということになる。これは「Something<T> where T: Transposable」などとジェネリックな型の制限だとしても同じだった。まあ書き方が違うだけで同じ意味だもんな。
ところがもちろん
protocol Transposable { var isValid: Bool { get } } struct Something<T> { } let obj = Something<Transposable>()みたいにプロトコルの継承をやめてなんでもよしとすると、プロトコルでも問題ない。プロトコルとしては全く同じなのに、何が違うんだろう。もちろんassociatedtypeを持っていたりするような、プロトコル宣言時点で決まらない場合とかがダメなのはわかるけど、他にもプロトコルが型として使えないことにときどき出くわす。よくわからない。
全然別の話なんだけど他にも、ジェネリクスにスタティックなインスタンスを作ろうとすると
struct Other<T> { static let name = "Other" }は
Static stored properties not supported in generic typesと、ジェネリクスにはスタティックな格納型プロパティはサポートしない、とある。ジェネリクスの宣言時点で型が決まらないから、ということだろうけど、この場合はスコープの違いだけで、どこかグローバルなところに確保して、そこをコンパイラが知っていればいいだけのことじゃないだろうか。まあ、こっちはあまり使い道はないので別にいいんだけど、なんでダメだということにするんだろう。
けっこうこういう、なんというか、機能が直交していないというか、細かいところでコンパイルできないことに出くわす。20年ほど前、Objective-Cを勉強し始めたころにこういう悩みはなかったような気がする。まあObjective-CはSwiftに比べると単純で、機能も限られている、ということかもしれないけど。
そういえばそのもっと昔、MPWでちまちま書くのをやめて、当時急速に流行りだしたCodeWarriorでPowerPlantを使うためにC++を勉強し始めたとき、C++の膨大さと複雑さに心が折れそうになった、というか結局心折れてしまってPlowerPlantとのインターフェイスだけC++で書いてあとはCで書いてた(というかC風の書き方でC++を書いてた。C++からCを呼ぶのは難しくないけどCからC++を呼ぶのは難しかった)。なんだかあれを思い出してしまう。
今考えるとPowerPlantもC++の機能のごく一部しか使ってなかったのに、全部を理解しようとして苦しんでいただけだったとは言える。もう25年以上前の話だけど、いまだにC++だけはまともに書けるとは思えない。多分もう死ぬまで書かないと思うけど。
どっちにしても実行時にクラッシュされるのに比べたらコンパイルできないことなんでむしろ喜ぶべきことで、もちろんSwiftの意図もそこにあるんだろうけど、Swiftで心折れたくないなあ。
2020-11-19 21:22
nice!(0)
コメント(0)
コメント 0