I am trying to extend from HashMap in order to override the put Method and register some data.
I have the following class:
class SomeClassExtendingHashMap : HashMap<String, Object>() {
}
I receive the following compilation error:
SomeClassExtendingHashMap.kt: (6, 7): Inherited platform declarations clash: The following declarations have the same JVM signature (getOrDefault(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;):
fun getOrDefault(key: Any!, defaultValue: Object!): Object!
fun getOrDefault(key: String, defaultValue: Object): Object
Per my understand getOrDefault from Kotlin is conflicting with Map.getOrDefault.
Is there a better way to handle that?
I just ran into the same issue when compiling with Gradle 3.2.1 and Kotlin 1.0.5-3. With Gradle 3.1 and the same version of Kotlin, the same code compiles just fine.
Iâm not sure why HashMap would show non-final in this case but I wanted to highlight how to do this with delegation again for future readers:
class MyMap<K, V> : MutableMap<K, V> by HashMap<K, V>()
Itâs good to remember that itâs a code smell to type variables as specified collection implementations. If you ever find yourself using ArrayList instead of List, or HashMap instead of Map it probably indicates your doing something wrong.
For example:
val a: HashMap<String, String> = HashMap() // likely code smell
val b: Map<String, String> = HashMap() // good
EDIT: To clarify, both a and b are HashMaps, but since in this case we donât care about the details of what kind of map (e.x. we donât care about big-O performance), we want to consider them as Maps.
@arocnies Future readers may, like me, be stuck with classic inheritance: the delegation pattern is certainly fantastic, but is not always applicable, especially when you have several constructors. And inheriting from a concrete collection class is definitely not a code smell.
I wasnât saying inheriting from a concrete collection is a code smell, I meant to say that typing variables, params, or return types as concrete collections is a code smell
Of course just because typing variables/params/return types to the class instead of the interface smells doesnât mean itâs wrongâthere are plenty of cases where itâs good to specify your collection implementation. Youâll want to type it to a specific concrete class if youâre writing an algorithm and trying to get specific big-O performance.
For some reason, itâs a common mistake for newer coders to do this at times where itâs incorrect.
EDIT: Although subclassing HashMap isnât a code smell in itself, subclassing anything to get its functionality usually is (which is the point âcomposition over inheritanceâ). For example, I once had a professor tell his students to subclass List in order to implement other collectionsâwhich was definitely wrong. If I was creating a custom Map collection in Java, unless I very specifically wanted it to be considered âis aâ HashMap, Iâd still use Java delegation to a private member of my class and extend the Map interface.