初めに
ジェネリクスにしないとなんで引数にできなくてエラーになるんだろうと思っていましたが、久々にteratilをのぞいていたら同じようなことを疑問に思っている質問があったので向き合って見ました。
で実際に質問されていたもの
https://teratail.com/questions/135893
再現したcodeの写真パシャっつ
※エラー内容違いますが…。
エラー内容の抜粋
Protocol 'b' can only be used as a generic constraint because it has Self or associated type requirements
エラー内容google翻訳
プロトコル「b」は、自己または関連付けられたタイプの要件があるため、汎用制約としてのみ使用できます
google翻訳の、'自己または関連付けられたタイプの要件があるため'←でここはどこなの
どうやら以下の部分みたいです。↓
associatedtype freedom
https://qiita.com/mshrwtnb/items/2f947eb8422899b84dbc
で書かれているようにこのassociatedtypeとはこれを継承するところで初めて型を決められるということ。最初からこの型が決められないということ。
上記のコードでいうとbで初めてこれをIntとして使いますと言っています。
ここら辺で『あー、なるほど、型が決められていないから直で入れられないんだ』と思う方もいますが以下でもう少し詳しく……
もう少し詳しく
class vcvva{
func abc(b:b){
print(b)
}
func abc1<T:b>(b:T){
}
}
なぜ上記の上の方だけでエラーが出るのか?
ここで、でもbで型決めているよね???と、思われた方いるのではないでしょうか?
ほらここ!
typealias freedom = Int
そもそも以下の部分はclassやstructで書くものなのにprotocoleでも宣言できてしまうのですよね。
protocoleのextensionでですが…
そもそもprotocoleのextensionは継承するclassに反映される記述という考え(私自身が、いやきっとあっているはず…)
なので
extension b{
typealias freedom = Int //freedomはIntの型にすることにしました。
func abc(a:freedom){
print("\(a + 1)")
}
}
こうやって書いている記述は以下の記述そのもの…無理やりすぎるのかな?
class abc:b{
typealias freedom = Int
func abc(a:freedom){
print("\(a + 1)")
}
}
…ってことは以下の記述だと、え?待ってbのfreedom型わからなくね?となるのです。
class vcvva{
func abc(b:b){
print(b)
}
}
で以下の記述だとbが継承されているクラスやらの指定だからあ、Tが継承されているクラスにfreedom型決めているから大丈夫だね!めでたし、めでたしとなるわけです。
class vcvva{
func abc1<T:b>(b:T){
}
}
おい!こら何言っとんじゃ?違うだろそれ!という方は優しく指摘していただければと思います。