Помощничек
Главная | Обратная связь


Археология
Архитектура
Астрономия
Аудит
Биология
Ботаника
Бухгалтерский учёт
Войное дело
Генетика
География
Геология
Дизайн
Искусство
История
Кино
Кулинария
Культура
Литература
Математика
Медицина
Металлургия
Мифология
Музыка
Психология
Религия
Спорт
Строительство
Техника
Транспорт
Туризм
Усадьба
Физика
Фотография
Химия
Экология
Электричество
Электроника
Энергетика

Вложенные и внутренние классы



Существует возможность определения одного класса внутри другого. Такие классы известны как вложенные (nested) классы. Область видимости вложенного класса ограничивается областью видимости включающего класса. Таким образом, если класс B определен в классе A, то B известен внутри A, но не вне его. Вложенный класс имеет доступ к членам класса (включая private-члены), в который он вложен. Однако включающий класс не имеет доступа к членам вложенного класса.

Существует два типа вложенных классов: статические и нестатические. Статический вложенный класс — это класс, который имеет модификатор static. Согласно своей характеристике он должен обращаться к членам своего включающего класса через объект. То есть он не может обратиться к членам включающего класса напрямую. Из-за этого ограничения статические вложенные классы используются редко.

Наиболее важный тип вложенного класса — внутренний (inner) класс. Внутренний класс – это нестатический вложенный класс, имеющий доступ ко всем переменным и методам своего внешнего класса и возможность обращаться к ним напрямую, таким же способом, как это делают другие нестатические члены внешнего класса. Итак, внутренний класс находится полностью в пределах видимости своего включающего класса.

Следующая программа показывает, как можно определять и использовать внутренний класс. Класс с именем Outer имеет одну переменную экземпляра с именем outer_x, один метод экземпляра с именем test() и определяет один внутренний класс с именем inner.

 

// Демонстрирует внутренний класс.

class Outer {

int outer_x = 100;

void test () {

Inner inner = new Inner();

inner.display();

}

// это внутренний класс

class Inner {

void display() {

System.out.println("В методе display: outer_x = " + outer_x);

}

}

}

class InnerClassDemo {

public static void main(String args[]) {

Outer outer = new Outer();

outer.test();

}

}

 

Вывод этой программы:

 

В методе display: outer_x = 100

 

В этой программе внутренний класс с именем inner определен в пределах области видимости класса outer. Поэтому любой код в классе inner может прямо обращаться к переменной outer. Внутри inner определен экземп-лярный метод с именем display(). Этот метод отображает outer_x в поток стандартного вывода. Метод main() класса InnerCiassDemo создает экземпляр (объект) класса outer и вызывает его метод test(). Тот метод создает экземпляр класса inner и вызывает метод display().

Важно понять, что класс inner известен только в пределах области действия (т.е. внутри) класса outer. Java-компилятор генерирует сообщение об ошибке, если какой-то код вне класса outer делает попытку создать экземпляр (объект) класса inner. Итак, вложенный класс ничем не отличается от любого другого программного элемента, но он известен только в пределах включающей его области.

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

 

// Эта программа компилироваться не будет.

class Outer {

int outer_x = 100;

void test() {

Inner inner = new Inner();

inner.display();

}

// это внутренний класс

class Inner {

int y = 10; // y - локальная для Inner

void display() {

System.out.println("В методе display: outer_x = " + outer_x);

}

}

void showy() {

System.out.println(y); //ошибка, у здесь неизвестна!

}

}

class InnerClassDemo2 {

public static void main(String args[]) {

Outer outer = new Outer();

outer.test ();

}

}

 

Здесь y объявлена как переменная экземпляра класса inner. Таким образом, она не известна вне этого класса, и не может использоваться методом showy().

Хотя мы сосредоточились на вложенных классах, объявленных в области внешнего класса, существует возможность определять внутренние классы в пределах любого блока. Например, можно определить вложенный класс в блоке, установленном в методе или даже в теле цикла for, как показывает следующая программа.

 

// Определение внутреннего класса в цикле for.

class Outer {

int outer_x = 100;

void test() {

for(int i=0; i<10; i++) {

class Inner {

void display() {

System.out.println("В методе display: outer_x = " + outer_x);

}

}

Inner inner = new Inner();

inner.display();

}

}

}

 

class InnerClassDemo3 (

public static void main(String args[]) {

Outer outer = new Outer();

outer.test ();

}

}

 

Вывод этой версии программы:

 

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

В методе display: outer_x = 100

 

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

Основы наследования

Чтобы наследовать класс, нужно просто включить определение одного класса в другое, используя ключевое слово extends. Чтобы увидеть, как это делается, начнем с короткого примера. Следующая программа создает суперкласс с именем A и подкласс с именем B. Обратите внимание, как используется ключевое слово extends, чтобы создать подкласс A.

 

 

// Простой пример наследования.

// Создать суперкласс

class A {

int i, j;

void showij () {

System.out.println("i и j: " + i + " " + j);

}

}

 

// Создать подкласс расширением класса а.

class B extends A {

int k;

void showk() {

System.out.println("k: " + k);

}

void sum() {

System.out.println("i+j+k: "+ (i+j+k) );

}

}

 

class Simplelnheritance {

public static void main(String args[]) {

A superOb = new A();

B subOb = new B();

// Суперкласс может быть использован сам по себе.

superOb.i = 10;

superOb.j = 20;

System.out.println("Содержимое superOb: ");

superOb.showij();

System.out.println();

/* Подкласс имеет доступ ко всем public-членам его суперкласса. */

subOb.i = 7;

subOb.j = 8;

subOb.k = 9;

System.out.println("Содержимое of subOb: ");

subOb.showij();

subOb.showk();

System.out.println();

System.out.println("Сумма i, j и k в subOb:");

subOb.sum();

}

}

 

Подкласс B включает все члены его суперкласса A. Вот почему объект subOb может обращаться к i и j и вызывать showij(). Поэтому же внутри sum() можно прямо ссылаться на i и j, как если бы они были частью B.

Хотя A – суперкласс для B, он тоже полностью независимый, автономный класс. Роль суперкласса для некоторого подкласса не означает, что этот суперкласс не может использоваться сам по себе. Более того, подкласс может быть суперклассом для другого подкласса.

Вывод этой программы:

 

Содержимое superOb:

i и j: 10 20

 

Содержимое of subOb:

i и j: 7 8

k: 9

 

Сумма i, j и k в subOb:

i+j+k: 24

 

Ниже показана общая форма объявления класса, который наследует суперкласс:

 

class subclass-name extends superclass-name {

// тело класса

}

 

где subclass-name – имя подкласса, superclass-name – имя суперкласса. Можно определять только один суперкласс для любого подкласса, который вы создаете. Java не поддерживает наследования множества суперклассов в одиночном подклассе. (Это отличает Java от С++, в котором можно наследовать множество базовых классов) Можно создавать иерархию наследования, в которой подкласс становится суперклассом другого подкласса. Никакой класс не может быть суперклассом самого себя.

 




Поиск по сайту:

©2015-2020 studopedya.ru Все права принадлежат авторам размещенных материалов.