open class IEquality { fun equals(other : Any) : Boolean = (this as java.lang.Object).equals(other as java.lang.Object) } open class IHashable : IEquality { val hashCode : Integer get() = (this as java.lang.Object).hashCode() } open class IMap { fun get(key : K) : V fun set(key : K, value : V) : V fun remove(key : K) : V fun containsKey(key : K) : Boolean } class HashableWrapper(val obj : Any) : IHashable // equals and hashCode implementations are inherited [inline] fun Any.hashable() : HashableWrapper = HashableWrapper(this) open class IHashingStrategy { fun equals(a : K, b : K) : Boolean fun hashCode(a : K) : Integer } class DefaultHashingStrategy : IHashingStrategy { override fun equals(a : K, b : K) : Boolean = a.equals(b) override fun hashCode(a : K) : Integer = a.hashCode } class JavaObjectHashingStrategy : IHashingStrategy { override fun equals(a : K, b : K) : Boolean = a.hashable().equals(b) override fun hashCode(a : K) : Integer = a.hashable().hashCode } class HashMap : IMap { private [inline] fun hashCode(a : K) = a.hashable().hashCode private [inline] fun equals(a : K, b : K) = a.hashable() == b // everything else uses these equals() and hashCode()... } class StrategyHashMap(hashingStrategy : IHashingStrategy) : IMap { // where !(K : IHashable) //this() : this(JavaObjectHashingStrategy()) {} //this() where (K : IHashable) : this(DefaultHashingStrategy()) {} //... }