Why Set and List interfaces have copy of several methods from Collection interface?
The stdlib code is below. Probably it is worth removing redeclaration and simplify public interfaces?
I can create create issue/PR is you want…
public interface Set<out E> : Collection<E> {
// Query Operations
override val size: Int
override fun isEmpty(): Boolean
override fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
/*....*/
}
/**
* A generic ordered collection of elements. Methods in this interface support only read-only access to the list;
* read/write access is supported through the [MutableList] interface.
* @param E the type of elements contained in the list. The list is covariant on its element type.
*/
public interface List<out E> : Collection<E> {
// Query Operations
override val size: Int
override fun isEmpty(): Boolean
override fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
// Bulk Operations
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
/*....*/
}
public interface Collection<out E> : Iterable<E> {
// Query Operations
/**
* Returns the size of the collection.
*/
public val size: Int
/**
* Returns `true` if the collection is empty (contains no elements), `false` otherwise.
*/
public fun isEmpty(): Boolean
/**
* Checks if the specified element is contained in this collection.
*/
public operator fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
// Bulk Operations
/**
* Checks if all elements in the specified collection are contained in this collection.
*/
public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
}
I personally like it the way it is. That way it’s easier to see what methods are part of List, Set. Yes, you could always check the methods defined in the parent interface but this way you have all of them in one place.
You could argue that this information is visible in the docs, but I generally prefer to just use IntelliJ “Jump to Declaration” to get this information and only use the docs if I have to. That way I don’t have to leave my IDE.
Just out of interest? Is there any downside to redeclaring methods in interfaces?
This is copy-pasting, so all related problems are here: you need to copy-paste documentation, etc.
I prefer expanding all such methods in IDE (probably with equals/toString/hashCode, etc.) if it is needed (just to cover all possible JVM interfaces).
Moreover, MutableSet doesn’t have copy-pasted methods (and this it cool from my point of view, because we can get a lot of them here).
public interface MutableSet<E> : Set<E>, MutableCollection<E> {
// Query Operations
override fun iterator(): MutableIterator<E>
// Modification Operations
/**
* Adds the specified element to the set.
*
* @return `true` if the element has been added, `false` if the element is already contained in the set.
*/
override fun add(element: E): Boolean
override fun remove(element: E): Boolean
// Bulk Modification Operations
override fun addAll(elements: Collection<E>): Boolean
override fun removeAll(elements: Collection<E>): Boolean
override fun retainAll(elements: Collection<E>): Boolean
override fun clear(): Unit
}
However please note, that idea “less unnecessary duplicated code here” is just my opinion. And if there is some logic from Kotlin authors - it is worth for me to know it.
My guess is that they are mimicking Java. As for why Java does it, my guess is that they do it in order to provide more specific Javadoc for the overriden methods. It also makes sense conceptually: List and Set overrides the contracts defined by Collection specifying additional requirements on the methods. Repeating them in code makes this more explicit.
Moreover, MutableSet doesn’t have copy-pasted methods (and this it cool from my point of view, because we can get a lot of them here).
Wrong. It’s overriding all the methods defined in MutableCollection, just like how Set is overriding the methods of Collection.
MutableSet overrides Set as well as Set overrides Collection.
However MutableSet doesn’t copy methods (they are inherited automatically), but Set has at least four methods, which could be omitted (because they are inherited automatically).
So my question is: why kotlin stdlib has this behaviour for Set/List interfaces?
Not a single method in Set and MutableSet is implicitly inherited from Collection and MutableCollection. All of them are explicitly redefined. This mirrors the definitions in Java, except that Java does not have separate read-only and mutable interfaces.