私の質問は、タイトルが言っていることのほとんどです:明示的な型キャストを許可しないプログラミング言語を持つことは可能ですか?
Base
言いたいことを明確にするために、親クラスと子クラスを持つ C# のような言語で作業していると仮定しますDerived
。明らかに、そのようなコードは安全です:
Base a = new Derived();
継承階層が上がるので安心ですが、
Dervied b = (Base)a;
降りるのは安全ではないため、安全は保証されません。
ただし、安全性に関係なく、このようなダウンキャストは多くの言語 (Java や C# など) で有効です。コードはコンパイルされ、型が正しくない場合は実行時に失敗します。したがって、技術的には、コードは依然として安全ですが、コンパイル時チェックではなく実行時チェックを介して行われます (ちなみに、私は実行時チェックのファンではありません)。
個人的には、少なくとも理論的な観点から、せいぜい信頼できるコードの観点から、コンパイル時の完全な型安全性が非常に重要であると考えています。コンパイル時の型安全性の結果として、キャストは不要になります (これは素晴らしいことだと思います。とにかく醜いからです)。キャストのような動作は、暗黙的な変換演算子またはコンストラクターによって実装できます。
だから私は疑問に思っています.現在、キャストが時代遅れであるほど厳密なタイプの安全性をコンパイル時に提供するオブジェクト指向言語はありますか? つまり、安全でない変換操作は一切許可されていませんか? それとも、これがうまくいかない理由がありますか?
ご意見ありがとうございます。
編集
例によって明確にすることができれば、これが私がダウンキャストをとても嫌う大きな理由です。
私が次のものを持っているとしましょう(大まかにC#のコレクションに基づいています):
public interface IEnumerable<T>
{
IEnumerator<T> GetEnumerator();
IEnumerable<T> Filter( Func<T, bool> );
}
public class List<T> : IEnumerable<T>
{
// All of list's implementation here
}
ここで、誰かが次のようなコードを書くことにしたとします。
List<int> list = new List<int>( new int[]{1, 2, 3, 4, 5, 6} );
// Let's filter out the odd numbers
List<int> result = (List<int>)list.Filter( x => x % 2 != 0 );
最後の行でキャストが必要であることに注意してください。しかし、それは有効ですか?一般的ではありません。List<T>.Filter
確かに、 の実装が別の を返すことは理にかなっていますList<T>
が、これは保証されていません ( の任意のサブタイプである可能性がありますIEnumerable<T>
)。ある時点でこれが実行されたとしても、後のバージョンでこれが変更される可能性があり、コードがいかに脆弱であるかが明らかになります。
ダウンキャストが必要だと私が考えることができるほとんどすべての状況は、この例のようなものになります。メソッドにはクラスまたはインターフェイスの戻り値の型がありますが、実装の詳細がいくつかわかっているため、結果をダウンキャストすることに自信があります。しかし、OOP は実装の詳細からの抽象化を実際に促進するため、これは反 OOP です。では、純粋な OOP 言語であっても、なぜそれを行うのでしょうか?