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>