6 июл. 2015 г.

Модификатор final для методов и классов.

Мы уже рассматривали ключевое слово final для полей и переменных. Но модификатор final может так же применятся к классам и методам. Смысл ключевого слова final зависит от контекста, но в основном оно означает: "Это нельзя изменить".

Теперь мы рассмотри модификатор final в контексте применения к методам и классам поскольку в данном случае это связано с наследованием и полиморфизмом, которые мы сейчас изучаем.

  • Если модификатор final стоит перед определением метода, то это означает, что этот метод не может быть переопределен (overrided) в классах наследниках.
  • Если модификатор final стоит перед определением класса, то это означает, что от этого класса не возможно унаследоваться.

Стоит отметить что метод объявленный как private, косвенно является final методом. Так как вы не можете получить доступ к private методу, то не можете его и переопределить.

GrabliИ вот тут возможны грабельки. Если вы не внимательно использовали модификатор private для какого-либо метода в суперклассе, а затем решили переопределить этот метод в подклассе, то переопределения или ожидаемого эффекта полиморфизма не произойдет и что более интересно, компилятор не выдаст ни какой ошибки, так как такой синтаксис является вполне легитимным и не нарушает выполнения программы. Этот момент я думаю стоит пояснить на примере. Но сперва еще раз прочитайте материал о полиморфизме.

Помните, там мы говорили что обычные методы всегда вызываются по версии объекта, а не ссылки на объект. Нижеприведенный пример чуть чуть сдвинет вашу парадигму :)

P0001

У нас есть суперкласс Root, от которого наследуется класс Branch. В классе Root есть метод prt(), а в классе наследнике Branch этот метод как бы переопределяется. Но на самом деле переопределения не происходит, так как метод prt() в классе Root имеет модификатор private. Поэтому метод prt() в классе Branch не переопределяет его, поскольку даже не может его увидеть. Метод prt() класса Branch это полностью новый метод.

Из того что мы знаем вполне естественно было бы ожидать что программа выведет как результат слово Branch, но  она выведет слово Root. А вот если в методе prt() класса Root убрать модификатор private, то выведется слово Branch.

 

Чтобы понять эту кухню надо объяснить что такое позднее и раннее связывание. Но об этом мы подробнее поговорим в одной из следующих статей.

P0002Сейчас же пока надо отметить что модификаторы final и private не совсем равнозначны. Верней их действие совсем разное. Модификатор private делает метод или поле доступным только в пределах класса и как следствие методы с модификатором private не могут быть переопределены в подклассах, поскольку эти методы даже не видны в подклассах. Это означает что подклассы не могут вызвать private методы суперклассов. Методы же объявленные как final доступны подклассам и могут быть ими вызваны, но не могут быть ими переопределены. Поэтому, как показано, на рисунке слева, при использовании модификатора final вместо private, компилятор выдаст ошибку.

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

Отправить комментарий