Предположим, что мы определяем интерфейс следующим образом:
interface Hashable {
int hash();
}
Теперь мы можем создавать классы, которые реализуют этот интерфейс.Например, класс List
:
class List<T> : Hashable {
int hash(){
int h = 0;
foreach(x in this){
h = combineHash(h,x.hash());
}
return h;
}
}
Проблема в том, что мы вызываем хеш для элементов внутри List<T>
, поэтому T должно быть Hashable
.Таким образом, мы должны сделать:
class List<T : Hashable> : Hashable {
... same here ...
}
С другой стороны, мы также хотим иметь возможность создавать списки с элементами, которые не могут быть хешируемыми.В этом случае мы просто не хотим, чтобы List<T>
реализовал Hashable
.Итак:
List<AHashableType> is itself Hashable
List<NotAHashableType> is not Hashable
Кроме того, мы хотим, чтобы метод хеширования был полиморфным (тип OO полиморфный, а не параметрически полиморфный).Поэтому, если мы создадим List<Foo>
с Bar
и Baz
внутри, где Foo
- это Hashable
, а Bar
и Baz
- это подтипы Foo
с различными hash()
методамитогда List<Foo>.hash()
должен вызывать правильный метод хеширования во время выполнения.
Это кажется основной вещью, которую языки должны уметь выражать.Один и тот же шаблон встречается в разных случаях, например, с ToString()
и с IComparable
.До сих пор я не нашел языка и решения на этом языке, который позволил бы мне выразить это безопасным способом.Знаете ли вы о таком языке и решении этого языка?Haskell довольно близко подходит к своим классам типов, но, к сожалению, они отправляются во время компиляции.