Что такое переопределение (overriding) метода в Java?

Если мы в нашем классе определяем метод с такой же сигнатурой, именем и возвращаемыми параметрами, что и в супер-классе — значит мы используем переопределение метода.  Никаких специальных слов добавлять не нужно, механизм работает автоматически при вызове метода.

Допустим у нас есть три класса: Dog,fox_size_comp Cat, Fox. Они наследуются от одного родителя с
названием Animal. В классе Animal есть метод say(), а классы-потомки переопределяют его. Затем мы садим животных в клетки и накрываем чёрной тканью. После этого мы можем подойти к любой клетке, качнуть её(не сильно) и попросить say(), зная лишь то, что внутри какое-то животное, но не зная какое точно. Мы получим именно тот звук, который переопределили в классе-потомке. Подробности в коде:

public class OverridingMethod {
    abstract static class Animal{
        public void say(){
            System.out.println("Заглушка");
        }
    }

    static class Cat extends Animal{
        public void say() {
            System.out.println("Кошка говорит Мяу-Мяу");
        }
    }

    static class Dog extends Animal{
        public void say() {
            System.out.println("Собака говорит Гав-Гав");
        }
    }

    static class Fox extends Animal{
        public void say() {
            System.out.println("Лисичка говорит фырфырфыр");
        }
    }

    public static void main(String[] args) {
        ArrayList<Animal> animals = new ArrayList<>();
        animals.add(new Cat());
        animals.add(new Dog());
        animals.add(new Fox());
        for (Animal animal :animals) {
            animal.say();
        }
    }
}

Вывод:
Кошка говорит Мяу-Мяу
Собака говорит Гав-Гав
Лисичка говорит фырфырфыр

Видно, что не смотря на то что все потомки приводятся к супер-классу при помещении в коллекцию, всё равно вызывается именно метод потомка, а не заглушка из родителя.

Давайте рассмотрим возможности, немного выходящие за рамки вопроса. Как вызвать вариант переопределённого метода, но находящийся в суперклассе? Для этого перед вызовом метода нужно написать слово super.

public class ExtendOverMeth {

    abstract static class Animal {
        public void say() {
            System.out.println("Заглушка");
        }
    }

    static class Fox extends Animal {
        public void say() {
            System.out.println("Лисичка говорит фырфырфыр");
            super.say();//Вызов метода суперкласса
        }
    }

    public static void main(String[] args) {
        new Fox().say();
    }

}

Вывод:
Лисичка говорит фырфырфыр
Заглушка

Можно защитить метод от переопределения если добавить к нему модификатор final. В этом случае при переопределении пользователь кода получит ошибку компиляции, которая в консоли всё прекрасно ему объяснит:

public class ExtendOverMeth {

    abstract static class Animal {
        final public void say() {
            System.out.println("Заглушка");
        }
    }

    static class Fox extends Animal {
        public void say() {
            System.out.println("Лисичка говорит фырфырфыр");
            super.say();//Вызов метода суперкласса
        }
    }

    public static void main(String[] args) {
        new Fox().say();
    }

}

Ошибка:
Error:(15, 21) java: say() in ExtendOverMeth.Fox cannot override say() in ExtendOverMeth.Animal
  overridden method is final

Также нельзя переопределять приватные методы родителя. Если Вы создадите у потомка такой же приватный метод, как и у родителя — это не будет переопределением.

Ещё нам в помощь существует аннотация @Override, которая защищает нас от ошибки неправильно переопределить метод. Если мы пометили метод как @Override и ошиблись в каком либо месте(указали неправильную сигнатуру) — компилятор не пропустит нас.

public class ExtendOverMeth {

    abstract static class Animal {
        void say() {
            System.out.println("Заглушка");
        }
    }

    static class Fox extends Animal {
        @Override
        String say() {
            super.say();
        }
    }

    public static void main(String[] args) {
        new Fox().say();
    }

}

Ошибка:
Error:(16, 16) java: say() in ExtendOverMeth.Fox cannot override say() in ExtendOverMeth.Animal
  return type java.lang.String is not compatible with void

 

Если Вас действительно заинтересовало, что же говорит лиса, можете послушать в видео:

Понравилась статья? Поделиться с друзьями:

Комментарии:

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: