2013-05-10 2 views
1

У меня есть класс myHashSet, который расширяет класс HashSet. myHashSet переопределяет методы add() и addAll() для HashSet. Таким образом, у меня есть следующий фрагмент кода:Почему super.addAll вызывает метод переопределенного добавления

class MyHashSet<E> extends HashSet<E> { 

    @Override 
    public boolean add(E e){ 
     return super.add(e); 
    } 

    @Override 
    public boolean addAll(Collection ? extends E> c){ 
     return super.addAll(c); 
    } 
} 

Я знаю, что метод addAll реализуется через Add(), то есть он использует метод добавления(). Итак, если я вызываю addAll MyHashSet, он должен вызывать addAll(), который, в свою очередь, должен вызывать HashSet's add(). Но почему он вызывает функцию добавления() MyHashSet, когда я вызываю addAll MyHashSet()?

Здесь я смущен, извините, если вопрос очень глупый.

+0

Это не так, как это работает. Поскольку 'add()' вызывается на 'this', а' this' является 'MyHashSet', то вызывается наиболее конкретная версия метода. –

+0

@DekDekku Но я использую super.addAll() и super.add(), которые должны ссылаться на метод суперкласса? Здесь нет ** этого **. – shar

+0

Вы используете 'super.addAll()' и 'super.addAll()' использует 'this.add()' (который по очереди делегирует 'super.add()', чтобы вы могли его просто удалить). –

ответ

4

Так работает полиморфизм.

Если у вас есть иерархия классов A и B, где B расширяет A, и вы получили переопределенный метод foo(), когда вы его вызываете, будет выполняться метод подкласса. Синтаксис super.foo() позволяет вызывать метод супер класса класса. Но если тогда метод суперкласса вызывает bar(), он будет вызывать версию, написанную в подклассе. Подумайте об этом: это позволяет наследованию работать, потому что вы можете переопределить методы суперкласса в подклассе и изменить функциональность.

3

Вы поменяли add(). Это означает, что когда add() вызывается на экземпляр MyHashSet, вы вызываете свой переопределенный метод. Не имеет значения, где находится сайт вызова: даже если он находится внутри метода супер-типа, будет вызываться ваш переопределенный метод. Почему вы ожидаете, что он будет работать иначе?

+1

+1 это суть наследования и ОО. – Bohemian

1

Последовательность вызова выглядит следующим образом:

  1. Вы называете MyHashSet::addAll()
  2. MyHashSet::addAll() звонки HashSet::addAll() использованием super->addAll()
  3. HashSet::addAll() вызовы MyHashSet::add() с помощью this->add()
  4. MyHashSet::add() вызовы HashSet::add() с помощью super->add()

В шагах 1 и 3 вызовы virtual, поэтому они вызывают последние реализации.

+1

Я думаю, что 'virtual' - скорее концепция C++, и упоминание об этом здесь может запутать новичков в Java. – Axel

0

MyHashSet's addAll()MyHashSet's add() метод внутри. Вы переопределили этот метод. Очевидно, он придет туда.

Смежные вопросы