Главная страница

Рабочая программа по дисциплине Цели и задачи освоения дисциплины Дисциплина Объектноориентированный анализ и программирование


Скачать 339.98 Kb.
НазваниеРабочая программа по дисциплине Цели и задачи освоения дисциплины Дисциплина Объектноориентированный анализ и программирование
Дата12.10.2022
Размер339.98 Kb.
Формат файлаdocx
Имя файлаobektno-orientirovannyj_analiz_i_programmirovanie_161021.docx
ТипРабочая программа
#730141
страница6 из 14
1   2   3   4   5   6   7   8   9   ...   14
public void printstring() {

System.out.printin(“This string was printed by TestWriter.”) ;

System.out.flush() ;

public static void main(String I. args) { StaticTestWriter.printString() ; TestWriter tw new TestWriter(); tw.printStrrngO ;

public class StaticTestWriter {

public static void printstring() {

System.out.printin(“This string was printed by StaticTestWriter.”) ;

System.out.flush();

В представленном примере метод printString класса StaticTestWriter может быть вызван без создания экземпляра через непосредственное обращение по имени класса. Для вызова же метода printString класса TestWritcr требуется создание экземпляра и обращение через имя конкретной сущности.

Важно также помнить, что статические поля являются общими для всех экземпляров класса. Это означает, что изменение значения ноля в одном месте приведет к изменению значения во всех экземплярах.

Конструкторы н деструкторы. Сборка мусора

Так как Java полностью объектно-ориентированный язык, и каждая сущность в нем является объектом, одним из наиболее важных элементов языка являются конструкторы.

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

Конструктор в Java выглядит как обычный метод, за тем исключением, что его имя должно совпадать с названием класса. Класс может иметь несколько конструкторов, но в таком случае их набор параметров должен отличаться с точки зрения компилятора (или методы должны отличаться сигнатурой). Рассмотрим следующий пример.

public class Rectangle { int width; int height;

public Rectangle () { this.width = 0; this.height = 0;

public Rectangle (int size) { this.width = size; this.height = size;

public Rectangle (int width, int height) { this.width = width; this.height = height;

В данном примере класс Rectangle содержит два поля — ширину и высоту — и три конструктора. Первый из них создает прямоугольник с нулевыми длиной и шириной, второй — квадрат, а третий — фигуру с заданным размерами. Java допускает ссылаться из одного конструктора на другой с помощью ключевого слова this (позволяет получить ссылку на экземпляр объекта с которым идет работа, то есть ссылку «на себя»). Таким образом, класс Rectangle может иметь также следующий вид.

public class Rectangle { int width;

int height;

public Rectangle () {
this(0, 0);


public Rectangle (int size) {
this(size, size);


}

public Rectangle (int width, int height) { this.width = width;

this.height = height;

}

Здесь первый и второй конструктор ссылаются на третий. Пользователь же, в соответствии с принципом инкапсуляции, нс знает о том, как организована работа конструкторов. Для него существует три различных способа создания объекта класса Rectangle, хотя на самом деле сущность создается единственным образом.

Для ограничения доступа к конструкторам, точно также как и для других методов, могут применяться модификаторы доступа protected и private.

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

Как было сказано выше, деструктор, в противовес конструктору, применяется для уничтожения экземпляра класса. Java, в отличие от большинства языков про1раммирования, не позволяет создавать деструкторы. Такое ограничение связано с тем, что в Java применяется механизм сборки мусора (garbage collection).

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

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

Единственным способом выполнить какие-либо действия при уничтожении объекта является использование метода finalize. Его каноническая форма выглядит следующим образом.

protected void finalized {

//...

Модификатор protected необходим для защиты от вызова метода из постороннего участка кода.

Инструкции, включенные в данный метод, будут выполнены при уничтожении объекта сборщиком мусора.

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

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

Наследование. Обращение к суперклассу

Н Java любой класс может являться наследником другого класса. При этом каждый класс может наследовать только от одного класса. Таким образом в Java решается характерная для многих языков программирования проблема множественного наследования.

Для того чтобы объявить класс-наследника, необходимо использовать ключевое слово extends. Если родительский класс не задан явным образом, то объект считается наследником класса Object. Рассмотрим следующий пример.

public class Parent {

public int a;

public int b;

public Parent(int a, int b) {

this.a = a;

this.b = b;

public void print(int a, int b) { if(a > b)

System.out.printin (“First argument is greater than second”) ;

else

if(a < b)

System.out.printin (“Second argument is greater than first”) ;

else

System. out. printin (“Arguments are equal”);

System.out.flush();

public class Child extends Parent {

public Children(int a) { super(a, 0) ;

public void print(int x) {

if+ b >= х)

System, out .printin (“Sum of a and b is greater or equal than argument”) ;

else

System. out.printi.n (“Sum of a and b is less than argument”) ;

System.out.flush ();

public static void main(String[] args) { Child ch new Child(l);

ch.print(2);

ch.print(1);

ch.print(100, 1);

ch.print(1, 100);

ch.print (100, 100);

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

Особое внимание стоит обратить на использование ключевого слова super, которое в данном контексте используется для вызова родительского конструктора. С его помощью может быть также выполнено обращение к переопределенному методу. Однако, пожалуй, самым важным назначением ключевого слова super является возможность обращения к суперклассу. Такая форма действует подобно ключевому слову this за тем исключением, что ссылка осуществляется на родителя. Обращение к членам суперкласса может быть выполнено с помощью следующей конструкции.

super.<член>;

Данная форма полезна в тех случая, когда из-за конфликта пространства имен могут быть скрыты некоторые элементы класса-родителя.

Пара методов print() иллюстрируют принцип полиморфизма в действии. В случае, когда метод вызывается с единственным аргументом, выполняется сравнение суммы полей и переданного параметра. Если же при вызове метода будет передана пара аргументов, то будет вызван унаследованный от родителя вариант метода, сравнивающий заданные параметры.

Хотя рассмотренный пример и не имеет большой практической ценности, он, тем не менее, позволяет получить представление о механизме наследования в Java.

Модификатор final

Модификатор final может быть применен к нолям, методам, классам и позволяет решить три задачи.

Если модификатор final применятся к полю, то его значение не может быть изменено в процессе работы. Таким образом, с помощью данного модификатора могут быть созданы константные значения.

public class Circle {

private final double pi = 3.14;

public double radius;

public Circle(double radius) {
this.radius = radius;


public double getSquareO { return pi * radius * radius;

}

В данном примере поле pi жестко нроассоциировано со значением 3,14. Подобное связывание положительно сказывается на скорости работы java-машины. Вторым назначением модификатора final является создание нснсрсопрсделясмых методов. То есть метод, объявленный как final, не может быть переопределен в классе-потомке.

public class Parent {

public final void print() {

System.out.printin(“This method has modifier final”);

System.out.flush();

}

public class Child extends Parent {

public void print() {

System.out .printin (“Error! ! !") ;

System.out.flush();

Представленный пример нс сможет быть скомпилирован, так как класс-наследник пытается переопределить метод с модификатором final.

Третьим назначением fianl является объявление классов, которые не могут иметь потомков.

public final class Parent {

public class Child extends Parent {

Представленный пример также приведет к ошибке времени компиляции, так как класс, имеющий модификатор final, не может быть расширен.

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

Абстракт ные классы и интерфейсы

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

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

Для создания абстрактного класса необходимо использовать при объявлении модификатор abstract. Абстрактные класс может содержать поля и методы. Если какой-либо метод такого класса является абстрактным, то он обязательно должен быть переопределен в классе-потомке. Пример абстрактного класса и его потомка представлен ниже.

1   2   3   4   5   6   7   8   9   ...   14


написать администратору сайта