scalaの構文は非常に有望です。私はもともとscalaは単なる快適なJava以上のものであり、まったく新しいプログラミングパラダイムを導入することができると考えましたが、構文によって許される多くの機能は意味論では間違っています。だから私はスカラの限界とハックを見つけてそれらを排除するための探求を始めました。私はちょうど他の視点からのスカラ方法とパターンに対応するためのテストプロジェクトを書いていますが。正確にタイプ消去が発生すると、
主な障害は、jvm実装から継承された型消去です。私は小さな消しゴムが壊れてしまった10の美しい模様を書くことができます。それは、タイプ消去がジェネリックを汚染すると言われていますが、私はミックスインでタイプ消去を偶然見つけました。私はそれがscalinのmixinの実現に問題であると考えます。ミックスインとミックスイン
trait B2 extends B1 {
def typeMe(x:T1 with T2) {}
}
ワーキングコードと
プリアンブル
trait T1
trait T2
trait B1 {
def typeMe(x:T1){}
}
壊れたコードは、別々の形質として宣言
trait T3 extends T1 with T2
trait B3 extends B1 {
def typeMe(x:T3) {}
}
エラーがある:
error: name clash between defined and inherited member:
method typeMe:(x: T1 with T2)Unit and
method typeMe:(x: T1)Unit in trait B1
have same type after erasure: (x: $line12.$read#$iw#$iw#T1)Unit
def typeMe(x:T1 with T2)
ベストプラクティスは何ですか?新しい特性を導入すると、(特に大きなミックスインチェーンの場合)冗長性があり、型の非互換性が生じます。疑似暗黙の引数を追加することは、オーバーヘッドを増加させるので、同様に銀色の弾丸ではありません。
更新:
私は非常に申し訳ありませんが、私は間違った質問をしてきました。私は説明されたエラーの性質上、その回避策ではなく、より多くのことに興味を持っています。型消去はどこで行われますか?タイプ消去ソースとみなされるコードにはジェネリックスがありません。コンパイラの動作の背後にある機構は何ですか?
オーバーロードされたメソッドの代わりに使用することもできます。別の名前を付けたり、型抜きパターンを使用したりします。 – Owen
'B3'では' typeMe'メソッドを 'B1'からオーバーライドするのではなく、それをオーバーロードしてサブタイプを取ることに気付きました。これは合法ですが、呼び出されるメソッドはローカル変数の型に依存するため、悪い考えです。すなわち、 'B3'オブジェクト' b3'と 'T3'オブジェクト' t3'を仮定すると、 'b3.typeMe(t3)'と 'b3.typeMe(t3:T1)'は異なるメソッドを呼び出します。 –