9. Java Переопределение и перегрузка методов | Библиофил — частный блог
Get Adobe Flash player

Переопределение метода
Переопределяя метод, принадлежащий родительскому классу, вы подписываете контракт.
Например, в нем говорится: «Я не принимаю никаких аргументов и возвращаю булево значение». Иными словами, аргументы и возвращаемые значения переопределяемых методов внешне должны выглядеть точно также, как в оригинальном методе родительского класса. Методы — это и есть контракт.
Если учесть полиморфизм, то при выполнении программы будет работать переопределенная классом Toaster версия метода turnOn(), которая унаследована от Appliance. Прежде чем решить, можете ли вы вызвать конкретный метод из ссылки, компилятор смотрит на ее тип. Если переменная Appliance ссылается на объект Toaster, то компилятор смотрит, есть ли у класса Appliance метод, который вызывается из ссылки типа Appliance. Но при выполнении программы JVM интересует не тип ссылки (Appliance), а сам объект Toaster, находящийся в куче.
Поэтому, если компилятор уже одобрил вызов метода, переопределенный метод имеет те же аргументы и тип возвращаемого значения, что и метод родительского класса.
Иначе кто-нибудь может вызвать из ссылки типа Appliance метод turnOn() без аргументов, несмотря на то что в классе Toaster этот метод принимает целочисленное значение. Какой же метод будет вызван? Метод, который находится в Appliance. Таким образом, метод turnOn(int level) в классе Toaster не переопределен.
Аргументы должны совпадать, а типы возвращаемых значений должны быть совместимы. Контракт для родительского класса определяет, как остальной код сможет использовать метод. Что бы он ни принимал в качестве аргументов, дочерний класс, переопределяя его, должен применять такие же аргументы. И что бы он ни возвращал, переопределенный метод должен возвращать значение того же или дочернего типа.
Помните, объект дочернего класса обязан уметь все, о чем объявил его родитель, поэтому безопасно возвращать дочерний класс в ситуациях, когда ожидается класс-родитель
Метод не может быть менее доступным. Это означает, что уровень доступа должен быть таким же или менее строгим.
Например, вы не можете переопределить публичный метод, сделав его приватным. Представьте, какой сюрприз получит внешний код, вызывая, как он считает на уровне компиляции, публичный метод, если внезапно во время выполнения программы JVM закроет дверь перед его носом, потому что вызванная переопределенная версия приватна!

Перегрузка методаэто не что иное, как наличие нескольких методов с одним именем, но разными наборами аргументов. И все. В процессе перегрузки методов полиморфизм не задействуется! Перегрузка позволяет создавать несколько версий одного метода с разным списком аргументов, делая их более удобными для вызова. Например, если у вас есть метод, который принимает только тип int, то перед вызовом этого метода код должен преобразовать, скажем, double в int. Перегрузив метод и добавив новую версию, принимающую double, вы упростите его вызов для внешнего кода. Хотя перегруженные методы и не пытаются соблюдать контракт для выполнения условий полиморфизма, они обладают гораздо большей гибкостью. Типы возвращаемых знчений могут быть разными. Вы можете изменять типы возвращаемых значений в перегруженных методах. При этом список аргументов тоже должен отличаться. Вы не можете изменить только тип возвращаемого значения. Если изменить лишь тип возвращаемого значения, это будет некорректная перегрузка — компилятор решит, что вы пытаетесь переопределить метод. Кроме того, это считается недопустимым, так как типы возвращаемых значений в дочернем классе и его родителе должны совпадать. Чтобы перегрузить метод, нужно изменить набор аргументов. При этом можно заменить тип возвращаемого значения любым другим. Вы можете как угодно изменять уровни доступа. При перегрузке есть возможность добавлять новые версии метода с более ограниченным доступом. Это не имеет значения, так как новый метод не обязан выполнять контракт перегружаемого метода.
Пример булевых функций
boolean frighten(int d) { System.out.println(«Гррррррр»); //будет работать если передали отличное от int d
return true; }

boolean frighten(int x) { System.out.println(«Укусить?»); //будет работать если передали int х
return false; }