![見出し画像](https://assets.st-note.com/production/uploads/images/96326882/rectangle_large_type_2_1cb71663d6d1982167288661c227dcf2.png?width=1200)
【Console Application】基本文法 31【学習記】
制御構造とか特殊な演算とかそういう手合の話🤤
Q.
`*` で宣言して arrayOf も `*` にすれば…?
A.
クラス宣言側が `*` だと arrayOf 側がエラーに🙄
→コンストラクタで手抜きオーバーロード用にジェネリクスを使おうとするのは無理
→その様な場合は諦めてコンストラクタでオーバーロードか Any で宣言して is で分岐
→型安全度を高めるにはコンストラクタのオーバーロードが良いかも(異論は認める
#学習記 #Kotlin
#Any #ジェネリクス #オーバーロード
ジェネリクスと Any
ファイルとデータベースで IntelliJ から離れる前に、どうにも気になった事が有るので試しておこうと思う😑
それはジェネリクスと Any の関係🤔
ファイルとデータベースではコンストラクタにジェネリクスを仕込んで初期化の変数型の対応を柔軟にしようと企んだわけだけど、ジェネリクスは配列の型を確定するとかの使い方が殆どで「初期化用引数は最終的に特定の型に変換されるのでジェネリクスで受け取りたい」というオーバーロードで手抜きをしたいという用途に使えないと判って断念したのよね😞
しかし移植を進める内に言語への理解が深まって lateinit 等を指定してあればコンストラクタが完全終了までに初期化できれば御咎め無しと成るのでセカンダリコンストラクタを並べてオーバーロードによる初期化用引数の型柔軟化が擬似的にできる事が判ってきたわけよ🤤
class A<T>(arg:T)
{
var value:String = arg.toString()
}
一番の問題はコンストラクタにジェネリクスを設定すると arrayOf() 等で配列化して使う時にどうしても(↑のクラスを例にすると) arrayOf<A<String>>() の様な固定した指定が必要となり配列使用が判っている場合に(例で言う String に)インスタンス生成時の引数の型が固定されてしまうという問題を抱えている事🙄
こいつに要素を足す場合、 `arg += A(arg:String)` で固定されてしまうって話😞
【Console Application】ファイルとデータベース 180【学習記】
Record
https://note.com/sayka/n/nfb69b289271d#29871ef3-b11c-42a8-abb9-2a3b33ae19d2
で、これ `arrayOf<A<*>>()` とか `class A(arg:Any)` でコンストラクタがジェネリクスとか、そういう解決ができないかなって思ってそれを実験しておきたいっていう話🤤
![](https://assets.st-note.com/img/1674512267147-gMN6hu14lB.jpg)
ここまでは Record でやったのとほぼ等価😑
本来は引数の型をどこかに記録しておかないと戻せないんだけど Record では RecordElement で DB の表の型を先に定義してあるのでそれを元に parse するという仕掛けなんだけど Int って定義しておいてデータ側が文字列だと例外出ちゃうのよねこれ🙄(まぁ今回は無視
この TestGenerics クラスは引数を文字列…というか toString() に掛けて全部文字列化して value に保持する、というクラス😑
なので arrayOf<TestGenerics>() ってできるのが一番いいんだけど…できなかった、というのが↑の学習記😞
で、今なら `<*>` じゃないの?って考えるわけなんだけど Any に変換される筈ではてどうなるか?🤔
![](https://assets.st-note.com/img/1674512317291-Z4SACAJGta.jpg)
この状態では勿論エラー…😞
型を固定すれば良いけどここに `*` を入れてみる🤤
![](https://assets.st-note.com/img/1674512331446-Grtnma7rty.jpg)
そりゃまぁ通るだろうよ🤤
問題はこれで違う型を放り込んで _init は分岐されるか否か😑
素直に考えると定義されているのは String と Boolean と不定の T で Any は不定の T へ流れて…となる気がする🤔
![](https://assets.st-note.com/img/1674512346112-OrXpsDYT2r.jpg)
ざっくり言うと atg[1] に入ってる true が 1 に変換されていれば勝利🤤
ではデバグ👇
![](https://assets.st-note.com/img/1674512360146-MPxRUsdUMV.jpg)
結論、想定通り不定 T を通る😞
というかこれ、 atg[i].value にしないとダメよね🙄
という事はコンストラクタを Any に変更して初期化関数をジェネリクス化しても Any として入ってくるって事かな😞
まぁ一応試そうか…
![](https://assets.st-note.com/img/1674512374178-9AKFsB25To.jpg)
そもそもこれだとダメっぽ😞
![](https://assets.st-note.com/img/1674512386363-15GYY8gBcf.jpg)
Any も勿論却下😞
![](https://assets.st-note.com/img/1674512402771-aXiq05L6Vv.jpg)
コンストラクタ引数が Any だと当然 _init は不定 T へ流れる…😞
![](https://assets.st-note.com/img/1674512456291-CtNblBEO6i.jpg)
そもそもオーバーロードで * は禁忌っぽい🙄
![](https://assets.st-note.com/img/1674512605550-9IHWez0PG1.jpg)
型判定の数が少ないならスマートキャストでイケるかな🤔
![](https://assets.st-note.com/img/1674512573568-1vchCwNBln.jpg)
`*` で受ける場合は明示的にキャストしないと駄目みたい😞
しかも arrayOf が TestGenerics<*> だと怒られるから TestGenerics に変えるとコンストラクタ引数で型誤りになるので Any で受けて型判定が FA っぽい😑
![](https://assets.st-note.com/img/1674512657590-thbbU3sWds.jpg)
………🙄
なんか想定通りになってない…😞
![](https://assets.st-note.com/img/1674512675429-slyxDdGL52.jpg)
………🤔
ちゃんと "1" になってるんだけど………🙄
………
あ、コンストラクタ最後に Any の _init 呼んでるからこれじゃだめぽ🤪
![](https://assets.st-note.com/img/1674512713055-dMoRmFr7XB.jpg)
ここは when の出番よー🤤
![](https://assets.st-note.com/img/1674512728691-ZcIG7TnQ8C.jpg)
ヨシ!👈🤪
結論
不定型引数で初期化するクラスを作る場合、ジェネリクスは使えない
セカンダリコンストラクタでオーバーロードか Any で受けて is で型判定の何れか
次回は
ファイルとデータベース学習へ復帰するぽ🤤