учебники, программирование, основы, введение в,

 

Java: механизмы наследования, ссылочные типы данных, интерфейсы, вложенные классы

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

  • расширение суперкласса путем добавления новых данных и методов;
  • замена методов суперкласса путем их переопределения;
  • слияние методов из суперклассов вызовом одноименных методов из соответствующих суперклассов.

Объявление класса
Объявление класса вводит новый ссылочный тип и определяет или часть или всю его реализацию.
При загрузке класса выделяется память для всех его статических переменных и затем выполняется их инициализация.
Объявление класса может иметь следующее формальное описание:
МодификаторыКласса  class  ИмяКласса
extends ИмяСуперКласса 
implements СписокРеализуемыхИнтерфейсов
{ТелоКласса}
Тело класса содержит описание переменных, методов и вложенных классов и заключается в фигурные скобки. В частном случае тело класса может не содержать ни одного объявления.
Например:
public class A implements B {
public A() {   }
public int Metod1(){return 0;}
}
interface B {
public int Metod1();
}
Вложенный класс описывается так же, как и внешний.
В описании каждого класса указывается имя класса и тело класса, содержащее объявления полей класса. Дополнительно для класса могут быть заданы модификаторы класса и указан непосредственный суперкласс и реализуемые классом интерфейсы. Полями класса в Java называются переменные и методы, определяемые в теле класса.
Класс может иметь более одного модификатора класса.
В языке программирования Java существуют следующие модификаторы класса:

  • abstract, являющийся модификатором реализации класса и определяющий, что класс может иметь абстрактные методы (методы, не имеющие реализации);
  • final, являющийся модификатором ограничения иерархии классов и указывающий, что класс не может иметь подклассов (не должен никогда появляться во фразе extends объявления класса). Класс с модификатором final обязан реализовать все свои интерфейсы.
  • public является модификатором доступа и указывает, что к данному классу разрешен доступ из других пакетов. Доступ может быть выполнен или непосредственно указанием квалифицированного имени класса, или с использованием оператора import.

Для указания модификаторов класса применяются следующие правила:

  • если класс, имеющий абстрактные методы, объявлен без модификатора abstract, то возникает ошибка компиляции;
  • для абстрактных классов нельзя создавать экземпляры класса;
  • если при объявлении класса не указан модификатор public, то класс доступен только внутри своего пакета;
  • при компиляции каждый общедоступный класс всегда записывается в отдельный файл с расширением .CLASS. Такой файл называется модулем компиляции;
  • имя общедоступного класса должно совпадать с именем файла, содержащего код класса на языке Java;
  • один модуль компиляции может содержать только один класс или интерфейс, имеющие модификатор public;
  • один модуль компиляции может одновременно содержать объявление общедоступного класса и нескольких интерфейсов или классов, не имеющих модификатора public;
  • один модуль компиляции не может одновременно содержать объявление общедоступного класса (public class) и общедоступного интерфейса (public interface);
  • объявление класса одновременно с модификаторами final и abstract вызывает ошибку компиляции.

Любой класс может иметь только один суперкласс, указываемый ключевым словом extends. Наследуемый суперкласс должен быть доступным классом и не иметь модификатора final.
По умолчанию предполагается, что в том случае, если для класса не указано никакого суперкласса, то его непосредственным суперклассом станет класс Object из пакета java.lang, который всегда является корневым классом в любой формируемой иерархии классов.
Раннее и позднее связывание
Раннее и позднее связывание является одним из проявлений полиморфизма, позволяя выполнять одним оператором вызов различных методов в зависимости от типа объекта.
В следующем примере оператор b.MyPrint() будет вызывать различные методы в зависимости от типа объекта, для которого он выполняется:
class B{    void MyPrint () {     }}
class B1 extends B{
void MyPrint () {   
//Переопределение метода
}
}
class B2 extends B{
void MyPrint () {   
//Переопределение метода
}
}
class B3 extends B{
void MyPrint () {       
//Переопределение метода
}
}
class PrintB{
B DoBObject () {   
// Метод, реализующий класс B
B b;
b= new B1();

b= new B2();

b= new B3();

return b;
}
...
B b= new PrintB.DoBObject();
b.MyPrint()     
// Выполняет вызов метода MyPrint в
// соответствии с типом объекта  b

http://localhost:3232/img/empty.gifОбъявление интерфейса

Объявление интерфейса вводит новый ссылочный тип, членами которого являются константы и абстрактные методы.
Реализация интерфейса всегда выполняется в классе, который использует данный интерфейс.
Один класс может реализовывать несколько интерфейсов, и один интерфейс может использоваться несколькими классами.
Интерфейсы позволяют разделять общую структуру - методы и константы, классами, не связанными между собой иерархией наследования.
Объявление интерфейса может иметь следующее формальное описание:
МодификаторИнтерфейса  ИдентификаторИнтерфейса
extends СписокНаследуемыхИнтерфейсов
{ТелоИнтерфейса}
Самым простым примером объявления интерфейса может быть следующий код:
interface MyColors {
int RED = 1, YELLOW = 2, BLUE = 4;
}
Интерфейс может иметь в качестве предков только интерфейсы.
Интерфейс может иметь модификаторы public и abstract. Язык Java подразумевает, что каждый интерфейс по умолчанию имеет модификатор abstract, который не рекомендуется указывать явно.
К интерфейсу, объявленному с модификатором доступа public, может быть произведен доступ из других пакетов, в противном случае - только из своего пакета.
Тело интерфейса заключается в фигурные скобки и не может содержать конструктора или блоков инициализации статических переменных. В остальном тело конструктора идентично телу абстрактного класса.
Любая переменная интерфейса по умолчанию считается переменной с модификаторами public, static и final и обязательно должна быть инициализирована константным выражением. Также каждая переменная в теле интерфейса неявно считается переменной с модификатором.
Метод, объявленный в теле интерфейса, по умолчанию считается методом с модификаторами abstract и public. Объявление метода завершается точкой с запятой и не содержит тела метода, заключенного в фигурные скобки.
Метод интерфейса не может иметь модификаторов final или static.
Интерфейс можно использовать как ссылочный тип при объявлении переменных. Переменная или выражение типа интерфейса могут ссылаться на любой объект, который является экземпляром класса, реализующего данный интерфейс. Переменную типа интерфейса можно использовать только после присвоения ей ссылки на объект ссылочного типа, для которого был реализован данный интерфейс.
Вложенные классы
Проблемы, возникающие из-за отсутствия множественного наследования, частично можно решить с использованием вложенных классов.
Если требуется, чтобы класс ClassA наследовал все доступные методы, включая и protected-методы, двух классов (класса ClassB и класса ClassC), то реализовать такую схему можно через вложенный класс.
Класс ClassA создается производным от класса ClassB. Это позволит всем экземплярам класса ClassA вызывать protected-методы класса ClassB.
В классе ClassA объявляется подкласс ClassFromC, производный от класса ClassC и переопределяющий все protected-методы класса ClassC, реализуя их как вызовы соответствующих методов из суперкласса.
При такой реализации экземпляр класса ClassA получает доступ к protected-методам двух различных классов - своего суперкласса и своего вложенного класса.
Абстрактные классы
Абстрактные классы содержат набор методов, который должен быть реализован в производном классе. Абстрактные классы и абстрактные методы помечаются модификатором abstract. Если в подклассе абстрактного суперкласса не выполнена реализация всех абстрактных методов, то подкласс по умолчанию также является абстрактным.

http://localhost:3232/img/empty.gifПриведение ссылочных типов

В языке Java преобразование ссылочных типов может происходить в четырех контекстах:

  • приведение;
  • присваивание;
  • вызов метода;
  • выполнение арифметических действий.

Наиболее общим случаем является приведение.
В языке Java объявление класса определяет одноименный ссылочный тип. Все переменные, имеющие ссылочный тип, указываемый именем класса, являются объектами. Тип такого объекта определяется оператором instanceof.
Например:
String str1;
Object ObjectName;
ObjectName =(Object) str1;
// Приведение типа

if (ObjectName instanceof String) {
// Тип объекта String
String str2 = (String) ObjectName ;
System.out.println(str2); 
// Запись в стандартный поток
// вывода значения строки,
// указанной параметром str2
}
В рассмотренном примере тип объекта str1 сначала приводится к типу своего косвенного суперкласса Object, а затем оператором instanceof определяется непосредственный тип объекта (при определении оператором instanceof типа объекта ObjectName как String или Object возвращается значение true).
При приведении ссылочных типов действуют следующие правила:

  • объект всегда может быть приведен к типу своего непосредственного суперкласса;
  • приведение ссылочных типов может выполняться по иерархии классов сколь угодно глубоко;
  • любой класс ссылочного типа всегда можно привести к типу Object.

После приведения объекта к типу суперкласса все переменные и методы самого класса объекта становятся недоступными для приведенного объекта.
Преобразование присвоением происходит в том случае, когда применяясь к переменной и значению, преобразует значение к типу переменной. При преобразовании присвоением не требуется проверки времени выполнения.
Значение простого типа не может быть присвоено значению ссылочного типа, как и значение ссылочного типа не может быть присвоено значению простого типа.
Присвоение значений ссылочного типа переменным ссылочного типа не требует во время выполнения действий преобразования. Просто компилятор должен иметь возможность преобразовать тип значения времени компиляции к типу переменной.
Например:
public class A { int x, y; }
public class ADerived extends A { int z; }
public interface B {    
void setColor(int color);
}
public class AB extends A implements B
{ int color;
public void setColor(int color) {
this.color = color;
}
}
class MyA{
public static void main(String[ ] args) {
// Создание переменных ссылочного типа
// и присваивание им значения:
A p = new A();
p = new ADerived();   
// Правильно: ADerived это
// подкласс класса A
ADerived p3d = p;     
// Ошибка

// Присваивание значения переменной
// типа Object:
Object o = p;         
// Правильно: любой объект приводим
// к типу  Object
int[ ] a = new int[3];
Object o2 = a;
// Правильно: массив приводим к Object

      // Присваивание значения переменной
// типа интерфейса:
AB cp = new AB();
B c = cp;             
// Правильно: AB реализует интерфейс  B

      // Присваивание значения переменной
// типа массива:
byte[ ] b = new byte[4];
a = b;                
// Ошибка: это массивы различных типов
ADerived[ ] p3da = new ADerived[3];
A[ ] pa = p3da;       
// Правильно: ADerived подкласс класса A
p3da = pa;            
// Ошибка, т.к. необходимо приведение
}
}
Преобразование приведением является более общим: если преобразование возможно, то приведение может его выполнить. Часто следует явно указывать преобразование приведением, чтобы компилятор имел строгую информацию о типе объекта. Для любого типа значения времени компиляции всегда можно выполнить приведение к тому же самому типу. Это позволит точно указать, что результирующее значение будет иметь именно указанный тип.
Приведением можно преобразовывать значения одного вычислимого типа к другому. Тип boolean не может быть приведен ни к какому другому типу.
Значения простых типов не могут быть приведены к значениям ссылочных типов и наоборот.
Эквивалентность объектов
Для определения равенства различных объектов применяется метод equals.
Метод equals реализован в классе Object и соответственно наследуем любым классом Java. Большинство классов переопределяет этот метод таким образом, что позволяет сравнивать на эквивалентность объекты конкретного класса.
Например:
class A {
String objectName;
A (String name) { objectName = name; }
// Конструктор
}
public class MyA {
public static void main (String args[ ])
{
A A = new A("Class1");     
// Создание экземпляра класса

A A_eq = A;                
// Ссылка на существующий объект

A A_clon = (A)A.clone;     
// Создание объекта методом clone

A A_2 = new A("Class2");
// Сравнение объектов:
if (A.equals(A_eq))    {  }
if (A.equals(A_ clon)) {  }
if (A.equals(A_ 2))    {  }
}
}
Выполнив приведенный пример, можно увидеть, что эквивалентными будут только экземпляр класса и объект, созданный как ссылка на данный экземпляр класса. А экземпляр класса и его клон, так же, как и различные экземпляры одного класса, не совпадают.
Принадлежность объекта к конкретному классу проверяется с помощью оператора instanseof.
Пакеты классов JDK
Инструментальный набор JDK включает утилиты и пакеты классов.
Собственно говоря, все стандартные возможности программирования на Java базируются на классах этого инструментального набора. JDK состоит из нескольких отдельных пакетов, иногда называемых библиотеками. Различные среды программирования, такие как JBuilder, предоставляют дополнительные пакеты классов.
Среда JBuilder 8 Enterprise полностью поддерживает работу со всеми классами пакета JDK 1.4.
http://localhost:3232/img/empty.gif

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г.Яндекс.Метрика