Reputation: 16067
If we consider the following class to count object added in an HashSet :
public class CountingHashSet<E> extends HashSet<E> {
public int addCount = 0;
@Override
public boolean add(E e) {
addCount +=1;
return super.add(e);
}
@Override
public boolean addAll(Collection<?
extends E> c) {
addCount += c.size();
return super.addAll(c);
}
}
Then, the JUnit test failed :
@Test
public void testCount() {
CountingHashSet<Integer> s = new CountingHashSet<>();
s.addAll(Arrays.asList(1, 2, 3, 4, 5));
for (int i = 6; i <= 10; ++i)
s.add(i);
assertEquals(10, s.addCount);
}
I get the following :
java.lang.AssertionError: expected:<10> but was <15>
Why I get 15 ? To my mind s.addAll(myCollection)
call super.addAll(c)
and if I look into the source code of hashSet
, I saw that addAll(c)
call add(e)
to add each element. But why super.addAll(c)
call the add method
that I redefined ? (that's why I get 15 instead of 10)
Upvotes: 1
Views: 2336
Reputation: 1502106
You're treating inheritance as if it were composition. It's not. The calls don't end up being "add()
on the HashSet
" - they end up being "add()
on the current object".
But why super.addAll(c) call the add method that I redefined ?
Because that's how virtual methods behave. addAll
just calls add()
, which will use the most overridden implementation in the actual type. That's how polymorphism always works. Let's write a simpler example:
class Superclass {
public void foo() {
bar();
}
public void bar() {
System.out.println("Superclass.bar()");
}
}
class Subclass extends Superclass {
@Override
public void bar() {
System.out.println("Subclass.bar()");
}
}
public class Test {
public static void main(String [] args) {
Superclass x = new Subclass();
x.foo(); // Prints Subclass.bar()
}
}
Is the result of Subclass.bar()
what you'd expect from this example? If so, what do you expect the difference would be in your version? Just because you're calling super.addAll()
doesn't mean that the object is suddenly in "non-overriding" mode or anything like that.
Upvotes: 5
Reputation: 13177
That's how polymorphism works. Your object is of type CountingHashSet
, so a call to add
will call CountingHashSet.add
, even from the super type.
Upvotes: 1