HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p><strong>Переопределение методов. Аннотация @Override</strong></p>
1 <p><strong>Переопределение методов. Аннотация @Override</strong></p>
2 <p>Переопределение метода (англ. Method overriding) - это возможность реализовать метод так, чтобы он имел идентичную сигнатуру с методом класса-предка, но предоставлял иное поведение, не вызывая коллизий при его использовании. Так же это один из инструментов реализации полиморфизма.</p>
2 <p>Переопределение метода (англ. Method overriding) - это возможность реализовать метод так, чтобы он имел идентичную сигнатуру с методом класса-предка, но предоставлял иное поведение, не вызывая коллизий при его использовании. Так же это один из инструментов реализации полиморфизма.</p>
3 <p>То есть, у нас может быть во всех классах потомках метод, у которого совпадают с методом класса-предка такие параметры: имя, перечень аргументов, возвращаемый тип, модификатор доступа. Отличия будут только в внутренней реализации этих методов. А использование таких одноименных методов не приведет к коллизии как, например, в случае с одноименными полями в методах и классах.</p>
3 <p>То есть, у нас может быть во всех классах потомках метод, у которого совпадают с методом класса-предка такие параметры: имя, перечень аргументов, возвращаемый тип, модификатор доступа. Отличия будут только в внутренней реализации этих методов. А использование таких одноименных методов не приведет к коллизии как, например, в случае с одноименными полями в методах и классах.</p>
4 <p>Переопределяя метод - обязательно помечайте его аннотацией @Override! Это не только спасет от потенциальных ошибок, но и повысит читаемость кода.<em><em>Переопределять можно только нестатические методы.</em></em></p>
4 <p>Переопределяя метод - обязательно помечайте его аннотацией @Override! Это не только спасет от потенциальных ошибок, но и повысит читаемость кода.<em><em>Переопределять можно только нестатические методы.</em></em></p>
5 <p>Рассмотрим это на примере классов пакета view части проекта "XO".</p>
5 <p>Рассмотрим это на примере классов пакета view части проекта "XO".</p>
6 <blockquote><p><a>Вот тут</a>можно скачать репу с кодом из примеров.</p>
6 <blockquote><p><a>Вот тут</a>можно скачать репу с кодом из примеров.</p>
7 </blockquote><p>Для начала, создадим вот такие классы:</p>
7 </blockquote><p>Для начала, создадим вот такие классы:</p>
8 <p>Благодаря @Override мы явно указываем, что метод show не просто какой-то локальный метод, а что это такой же метод, как и в классе-предке, но с новым поведением. В данном случае - сообщением.</p>
8 <p>Благодаря @Override мы явно указываем, что метод show не просто какой-то локальный метод, а что это такой же метод, как и в классе-предке, но с новым поведением. В данном случае - сообщением.</p>
9 <p><strong>И что это нам дает?</strong></p>
9 <p><strong>И что это нам дает?</strong></p>
10 <p>Переопределение методов дает возможность вызывать методы классов-наследников через ссылки классов предков. Что кажется противоречит принципу доступности членов классов в наследовании в java (потомкам доступны свойства предков, а не наоборот).</p>
10 <p>Переопределение методов дает возможность вызывать методы классов-наследников через ссылки классов предков. Что кажется противоречит принципу доступности членов классов в наследовании в java (потомкам доступны свойства предков, а не наоборот).</p>
11 <p>Напомним, невозможность вызывать члены потомка из предка, на примере следующего кода:</p>
11 <p>Напомним, невозможность вызывать члены потомка из предка, на примере следующего кода:</p>
12 <p>Результатом работы трех вызовов метода printName будет одна и та же надпись: It is a view.. Копируйте код, пробуйте! Потому что ссылка someView ограничена типом View и не может получить доступ к полям потомков класса View. Несмотря на идентичность имен этих полей.</p>
12 <p>Результатом работы трех вызовов метода printName будет одна и та же надпись: It is a view.. Копируйте код, пробуйте! Потому что ссылка someView ограничена типом View и не может получить доступ к полям потомков класса View. Несмотря на идентичность имен этих полей.</p>
13 <p><strong>А как вызвать метод потомка из ссылки типа предка?</strong></p>
13 <p><strong>А как вызвать метод потомка из ссылки типа предка?</strong></p>
14 <p>Просто вызвать, если он там переопределен. Перепишем пример вызовов так:</p>
14 <p>Просто вызвать, если он там переопределен. Перепишем пример вызовов так:</p>
15 <p>Теперь на экран будет выведено три различных сообщения: Метод класса View., Сообщение из класса SecondView., Сообщение из класса ThirdView..</p>
15 <p>Теперь на экран будет выведено три различных сообщения: Метод класса View., Сообщение из класса SecondView., Сообщение из класса ThirdView..</p>
16 <p><strong>Как это работает?</strong></p>
16 <p><strong>Как это работает?</strong></p>
17 <p>Даже в байткоде скомпилированной программы будет происходить вызов метода show у типа View. Но в момент исполнения этого байткода JVM получит ссылку на конкретный объект и полезет смотреть его перечень методов (vtable). В этой таблице находятся ссылки на все методы текущего объекта. И, в нашем случае, метод show там будет, даже если бы мы его не переопределили ни в одном из потомков. Если бы мы show не переопределили ни в одном из потомков, то в vtable их объектов (инстансов) была бы ссылка на один и тот же метод show класса View. Но, поскольку мы таки переопределили метод show, то в vtable каждого объекта класса-потомка будет ссылка не на родительский метод show, а на свой локальный переопределенный метод show.</p>
17 <p>Даже в байткоде скомпилированной программы будет происходить вызов метода show у типа View. Но в момент исполнения этого байткода JVM получит ссылку на конкретный объект и полезет смотреть его перечень методов (vtable). В этой таблице находятся ссылки на все методы текущего объекта. И, в нашем случае, метод show там будет, даже если бы мы его не переопределили ни в одном из потомков. Если бы мы show не переопределили ни в одном из потомков, то в vtable их объектов (инстансов) была бы ссылка на один и тот же метод show класса View. Но, поскольку мы таки переопределили метод show, то в vtable каждого объекта класса-потомка будет ссылка не на родительский метод show, а на свой локальный переопределенный метод show.</p>
18 <p>Вот так java понимает какой именно метод стоит вызывать в работе с переопределением методов.</p>
18 <p>Вот так java понимает какой именно метод стоит вызывать в работе с переопределением методов.</p>
19 <p>В предыдущем уроке было сказано, что все классы в мире java прямо или опосредовано наследуются от класса Object. И Вы самостоятельно можете провести эксперименты в коде, по этой теме. В файлах, из выше упомянутого репозитория, Вы можете найти класс Board с переопределенным методом класса Object - toString(). Попробуйте реализовать свои toString() для остальных классов, протестируйте их. Так же попробуйте добавить в View-классы методы gеtName() и вызвать их из класса Main.</p>
19 <p>В предыдущем уроке было сказано, что все классы в мире java прямо или опосредовано наследуются от класса Object. И Вы самостоятельно можете провести эксперименты в коде, по этой теме. В файлах, из выше упомянутого репозитория, Вы можете найти класс Board с переопределенным методом класса Object - toString(). Попробуйте реализовать свои toString() для остальных классов, протестируйте их. Так же попробуйте добавить в View-классы методы gеtName() и вызвать их из класса Main.</p>
20 <h2>Полезные ссылки</h2>
20 <h2>Полезные ссылки</h2>
21 <ul><li><a>Inheritance</a></li>
21 <ul><li><a>Inheritance</a></li>
22 <li><a>Overriding</a></li>
22 <li><a>Overriding</a></li>
23 </ul>
23 </ul>