русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Наследование и завершающие действия


Дата добавления: 2015-06-12; просмотров: 694; Нарушение авторских прав


Если при создании нового класса используется композиция и наследование, обычно вам не приходится беспокоиться о проведении завершающих действий — подобъекты уничтожаются сборщиком мусора. Но если вам необходимо провести завершающие действия, создайте в своем классе метод dispose() (в данном разделе я решил использовать такое имя; возможно, вы придумаете более удачное название). Переопределяя метод dispose() в производном классе, важно помнить о вызове версии этого метода из базового класса, поскольку иначе не будут выполнены завершающие действия базового класса. Следующий пример доказывает справедливость этого утверждения:

//: polymorphism/Frog.java

// Наследование и завершающие действия.

package polymorphism;

import static net.mindview.util.Print.*;

 

class Characteristic {

private String s;

Characteristic(String s) {

this.s = s;

print("Creating Characteristic " + s);

}

protected void dispose() {

print("disposing Characteristic " + s);

}

}

 

class Description {

private String s;

Description(String s) {

this.s = s;

print("Creating Description " + s);

}

protected void dispose() {

print("disposing Description " + s);

}

}

// живое существо

class LivingCreature {

private Characteristic p =

new Characteristic("is alive");

private Description t =

new Description("Basic Living Creature");

LivingCreature() {

print("LivingCreature()");

}

protected void dispose() {

print("LivingCreature dispose");

t.dispose();

p.dispose();

}

}

// животное

class Animal extends LivingCreature {

private Characteristic p =

new Characteristic("has heart");

private Description t =

new Description("Animal not Vegetable");



Animal() { print("Animal()"); }

protected void dispose() {

print("Animal dispose");

t.dispose();

p.dispose();

super.dispose();

}

}

// земноводное

class Amphibian extends Animal {

private Characteristic p =

new Characteristic("can live in water");

private Description t =

new Description("Both water and land");

Amphibian() {

print("Amphibian()");

}

protected void dispose() {

print("Amphibian dispose");

t.dispose();

p.dispose();

super.dispose();

}

}

// лягушка

public class Frog extends Amphibian {

private Characteristic p = new Characteristic("Croaks");

private Description t = new Description("Eats Bugs");

public Frog() { print("Frog()"); }

protected void dispose() {

print("Frog dispose");

t.dispose();

p.dispose();

super.dispose();

}

public static void main(String[] args) {

Frog frog = new Frog();

print("Bye!");

frog.dispose();

}

}

<spoiler text="Output:">

Creating Characteristic is alive

Creating Description Basic Living Creature

LivingCreature()

Creating Characteristic has heart

Creating Description Animal not Vegetable

Animal()

Creating Characteristic can live in water

Creating Description Both water and land

Amphibian()

Creating Characteristic Croaks

Creating Description Eats Bugs

Frog()

Bye!

Frog dispose

disposing Description Eats Bugs

disposing Characteristic Croaks

Amphibian dispose

disposing Description Both water and land

disposing Characteristic can live in water

Animal dispose

disposing Description Animal not Vegetable

disposing Characteristic has heart

LivingCreature dispose

disposing Description Basic Living Creature

disposing Characteristic is alive

</spoiler> Каждый класс в иерархии содержит объекты классов Characteristic и Description, которые также необходимо «завершать». Очередность завершения должна быть обратной порядку инициализации в том случае, если объекты зависят друг от друга. Для полей это означает порядок, обратный последовательности объявления полей в классе (инициализация соответствует порядку объявления).

В базовых классах сначала следует выполнять финализацию для производного класса, а затем — для базового класса. Это объясняется тем, что завершающий метод производного класса может вызывать некоторые методы базового класса, для которых необходимы действительные компоненты базового класса. Из результатов работы программы видно, что все части объекта Frog будут финализованы в порядке, противоположном очередности их создания.

Также обратите внимание на то, что в описанном примере объект Frog является «владельцем» встроенных объектов. Он создает их, определяет продолжительность их существования (до тех пор, пока существует Frog) и знает, когда вызывать dispose() для встроенных объектов.

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

//: polymorphism/ReferenceCounting.java

// Уничтожение совместно используемых встроенных объектов

import static net.mindview.util.Print.*;

 

class Shared {

private int refcount = 0;

private static long counter = 0;

private final long id = counter++;

public Shared() {

print("Creating " + this);

}

public void addRef() { refcount++; }

protected void dispose() {

if(--refcount == 0)

print("Disposing " + this);

}

public String toString() { return "Shared " + id; }

}

 

class Composing {

private Shared shared;

private static long counter = 0;

private final long id = counter++;

public Composing(Shared shared) {

print("Creating " + this);

this.shared = shared;

this.shared.addRef();

}

protected void dispose() {

print("disposing " + this);

shared.dispose();

}

public String toString() { return "Composing " + id; }

}

 

public class ReferenceCounting {

public static void main(String[] args) {

Shared shared = new Shared();

Composing[] composing = { new Composing(shared),

new Composing(shared), new Composing(shared),

new Composing(shared), new Composing(shared) };

for(Composing c : composing)

c.dispose();

}

}

<spoiler text="Output:">

Creating Shared 0

Creating Composing 0

Creating Composing 1

Creating Composing 2

Creating Composing 3

Creating Composing 4

disposing Composing 0

disposing Composing 1

disposing Composing 2

disposing Composing 3

disposing Composing 4

Disposing Shared 0

</spoiler> В переменной static long counter хранится количество созданных экземпляров Shared. Для счетчика выбран тип long вместо int для того, чтобы предотвратить переполнение (это всего лишь хороший стиль программирования; в рас­сматриваемых примерах переполнение вряд ли возможно). Поле id объявлено со спецификатором final, поскольку его значение остается постоянным на протяжении жизненного цикла объекта.

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

 



<== предыдущая лекция | следующая лекция ==>
Порядок вызова конструкторов | Поведение полиморфных методов при вызове из конструкторов


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.19 сек.