Spiral group

_________________________________________________________________________________

 

< Раздел “Язык Java > < Раздел “Технологии Java > < Основная страница >

 

Наследование в Java

 

Статья опубликована: 24.04.2006

 

 

Наследование (inheritance) - это процесс, посредством которого один объект может приобретать свойства другого. Точнее, объект может наследовать основные свойства другого объекта и добавлять к ним черты, характерные только для него. Наследование позволяет поддерживать концепцию иерархии классов. Применение иерархии классов делает управляемыми большие потоки информации.

Без использования иерархии классов, для каждого объекта пришлось бы задать все характеристики, которые бы полностью его определяли. Однако при использовании наследования можно описать объект путём определения того общего класса (или классов), к которому он относится, с теми специальными чертами, которые делают объект уникальным.

 

Модификаторы доступа Модификаторы доступа можно рассматривать как с позиции инкапсуляции так и наследования. Если рассматривать с позиции наследования, то модификаторы доступа позволяют путем установки доступа указать члены класса, которые будут наследоваться классом наследником автоматически, а какие нет. Например, переменная или метод, объявленная как public в данном классе будет автоматически перениматься в классе потомке.

 

Модификатор доступа

Область доступа

public

Без ограничений

private

Только из данного класса

protected

Из данного класса и его потомков

Без модификатора

Для всех классов данного пакета

 

Классы-адаптеры и внутренние классы как альтернатива множественному наследованию.

Большинство интерфейсов имеет больше, чем один метод. Даже если необходимо использовать только один метод, он все равно должен определить (пустыми) все остальные. Это загромождает программу и делает ее плохо читаемой. Для сокращения кода используются адаптеры и внутренние классы. Классы-адаптеры удобны для интерфейсов, имеющих более одного метода, поскольку определение всех функций для интерфейсов не относится к классам.

 Как известно, в Java запрещено множественное наследование от классов, в отличие от интерфейсов. Что же делать, если пользователь хочет наследовать класс-адаптер и какой-то другой класс одновременно, например, Applet ? Решение этой проблемы состоит в применении внутреннего класса, расширяющего адаптер. Ниже приведен фрагмент кода с внутренним классом:

 

public class MyClass extends Applet

{
     ...

     // Конструктор
     MyClass()

     {

          addMouseListener(new MyAdapter());

     }
     ...

     // Внутренний класс, расширяющий адаптер.
     class MyAdapter extends MouseAdapter

     {
          public void mouseClicked(MouseEvent e)

          {
               ...//Код обработки события.
          }
     }
}

 

Можно еще больше сократить код, если использовать анонимное (без имени) определение внутреннего класса следующим образом.

public class MyClass extends Applet

{
     ...
     //
Конструктор
     MyClass()
     {
          addMouseListener(new MouseAdapter()

          {
               public void mouseClicked(MouseEvent e)

               {
                    ...//Код обработки события
               }
          });
     }
     ...
}

 

Наследование через понижающее и повышающее преобразования типов

 

Наследования классов предусматривает возможности преобразования типов между суперклассом и подклассом. Различаются два вида преобразований типов — upcasting и downcasting. Повышающее преобразование (upcasting) — это преобразование от типа порожденного класса (от подкласса) к базовому (суперклассу). Такое преобразование допустимо всегда. На него нет никаких ограничений и для его проведения не требуется применять никаких дополнительных синтаксических конструкций. Это связано с тем, что объект подкласса всегда в себе содержит как свою часть объект суперкласса.

Понижающее преобразование (downcasting) — это преобразование от суперкласса к подклассу. Такое преобразование имеет ряд ограничений. Во-первых, оно может задаваться только явно при помощи операции преобразования типов, например,

 

B b1 = (B) a;

 

Во вторых, при преобразовании должен использоваться соответствующий тип. Если это не так, то возникает исключение ClassCastException в процессе выполнения программы.

При понижающем преобразовании часто применяется операция instanceof. Эта операция проверяет, имеет ли ее левый операнд класс, заданный правым операндом. Например,

if ( a instanceof B ) b1 = (B)a;

Пример, сочетающий в себе преобразования типов и instanceof:

 

Рассмотрим иерархию классов Issue — печатное издание, Book — книга, Newspaper - газета, Journal — журнал, где Book, Newspaper и Journal являются наследниками класса Issue.

public class Issue

{

    String name;

    public Issue(String name)

    {

        this.name = name;

    }

    public void printName(PrintStream out)

    {

         out.println("Наименование:");

         out.println(name);

    }

    . . .

}

 

public class Book extends Issue

{

    String authors;

    public Book(String name, String authors)

    {

        super(name);

        this.authors = authors;

    }

 

    public void printAuthors(PrintStream out)

    {

         out.println("Авторы:");

         out.println(authors);

    }

    . . .

}

А где-то в программе присутствует такой фрагмент:

Issue[] catalog = new Issue[]

{

     new Journal("Play Boy"),

     new Newspaper("Спид Инфо"),

     new Book("Война и мир", "Л.Толстой")

};

. . .

for(int i = 0; i < catalog.length; i++)

{

     if ( catalog[i] instanceof Book )

          ((Book) catalog[i]).printAuthors(System.out);

     catalog[i].printName(System.out);

}

 

Порождается каталог (массив печатных изданий), причем каждое из печатных изданий каталога может быть как книгой, так и газетой или журналом. При построении массива выполняется приведение к базовому типу (upcasting). Далее в цикле мы печатаем информацию из каталога. Причем, для книг кроме наименования печатается еще и список авторов. Для этого с использованием операции instanceof проверяется тип печатного издания, а при самой печати списка авторов элемент каталога преобразуется к типу Book. Если этого не сделать, транслятор выдаст ошибку, т.к. метод printAuthors(...) есть только в классе Book, но не в классе Issue.

 

Запрет наследования или переопределения  с помощью ключевого слова final

Если нужно запретить переопределение (overriding) метода во всех порожденных классах, то этот метод можно описать как final. Кроме того, ключевое слово final может применяться к классам. Это означает, что данный класс не может быть унаследован другим классом.

 

Множественное наследование интерфейсов

Интерфейсы допускают множественное наследование. Один класс при этом может удовлетворять нескольким интерфейсам сразу. В этом состоит серьезное отличие интерфейсов от обычных классов и от абстрактных классов. Интерфейсы не порождают проблем с множественным наследованием, поскольку они не содержат полей.

После этого может следовать ключевое слово extends и список интерфейсов, от которых будет наследоваться объявляемый интерфейс. Родительских типов может быть много, главное, чтобы не было повторений, и чтобы отношение наследования не образовывало циклической зависимости.

Наследование интерфейсов действительно очень гибкое. Так, если есть два интерфейса A и B, причем B наследуется от A, то новый интерфейс C может наследоваться от них обоих. Указание наследования от A является избыточным, все элементы этого интерфейса и так будут получены по наследству через интерфейс B.

 

public interface Drawble extends Colorable, Resizable

{

}

 

 

 

Ссылки:

 

1. Интернет университет информационных технологий http://www.intuit.ru/department/pl/javapl/6/javapl_6.html

2. Игнатьев А.А. Использование пакета Java Foundation Classes (Swing) для разработки пользовательских приложений на различных платформах http://www.csa.ru/skif/kurs_4/JAVA_BOOK/java_swing_book.html

3. Александр Поточкин Множественное наследование в Java Противоречия и способы их решения. http://www.javaportal.ru/java/articles/mnj.html

4. В. Фесюнов Конспект лекций по Java. http://lab253.kture.kharkov.ua/library/j2se/books/Fesunov_Konspekt/lesson8/index.htm

 

 

Автор:

 

 

Загребин Виктор Александрович

 

 

< Раздел “Язык Java > < Раздел “Технологии Java > < Основная страница >

 

Hosted by uCoz