Вложенные классы и интерфейсы

Preview:

Citation preview

Вложенные классы и интерфейсы.

Виталий Унгурян unguryan@itstep.org

Вложенный класс

Вложенный класс - это класс, который объявлен

внутри тела другого класса. 

Вложенные классы

Вложенные классы делятся на два вида: статические не статические.

Вложенные классы

Вложенные классы, объявленные как статические называются вложенными статическими (static nested classes). Не статические называются внутренними (inner classes).

Вложенные классы (nested)

class OuterClass {    ...    static class NestedClass {        ...    }}

Вложенные классы (inner)

class OuterClass {    ...    class NestedClass {        ...    }}

Доступ к переменным

Статические — не имеют доступ к членам обрамляющего класса. Как и другие поля класса, вложенные классы могут быть объявлены как private, public, protected или package private.

Доступ к переменным

Не статические классы имеют доступ к полям

обрамляющего класса, даже если они объявлены как

private.

Использование вложенных классов

Это хороший способ группировки классов, которые используются только в одном месте:

Если класс полезен (используется) только внутри одного класса, то логично будет держать их вместе. Вложение таких вспомогательных классов делает код более удобным.

Использование вложенных классов

Инкапсуляция: Допустим, есть два класса A и B,

классу B требуется доступ к свойству класса A, которое может быть приватным. Вложение класса B в класс A решит эту проблему, более того сам класс B можно скрыть от внешнего использования.

Использование вложенных классов

Улучшение читаемости и обслуживаемости кода:

Вложение малых классов в более высокоуровневые классы позволяет хранить код там, где он используется.

Доступ к вложенным классам

Доступ к вложенному классу осуществляется с помощью следующей конструкции:OuterClass.StaticNestedClassСинтаксис создания объекта вложенного класса:OuterClass.StaticNestedClass nestedObject =  new OuterClass.StaticNestedClass();

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

Внутренние (не статические) классы, как переменные и методы связаны с объектом внешнего класса.

Внутренние классы так же имеют прямой доступ к полям внешнего класса.

Ограничения внутрених классов

Внутренние классы не могут содержать в себе статические методы и поля.

Внутри внутренних классов нельзя объявлять перечисления.

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

Внутренние классы не могут существовать без экземпляра внешнего.

Создание объекта внутреннего класса

Outer outerObject = new Outer();Outer.Inner innerObject = outerObject.new Inner();

Пример внутренних классов

public class OuterClass {     public void method() { ... }      public class InnerClass {         public void method() { ... }                  public void anotherMethod() {             method();         }     } } 

Затенение (shadowing)

Если вы объявляете переменную (будь то параметр или свойство класса) в какой-либо области (например, вложенный класс или область метода) с именем уже занятым в данной области, то такое объявление «затеняет» предыдущее и вы не сможете обращаться напрямую к переменной по её имени.

Пример затенения

public class ShadowTest {    public int x = 0;    class FirstLevel {        public int x = 1;        void methodInFirstLevel(int x) {            System.out.println("x = " + x);            System.out.println("this.x = " + this.x);            System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);        }    }   

Пример затенения

    public static void main(String... args) {        ShadowTest st = new ShadowTest();        ShadowTest.FirstLevel fl = st.new FirstLevel();        fl.methodInFirstLevel(23);    }}

Локальные классы

Локальные классы похожи на внутренние: они не могут содержать статические поля или методы.

Ограничения локальных классов

У локальных классов есть множество ограничений:Они видны только в пределах блока, в котором объявлены;Вы не сможете объявить интерфейс внутри метода — интерфейсы статичны.

Ограничения локальных классов

Локальный класс может содержать статические поля, только если они константы.

Они не могут быть объявлены как private, public, protected или static;

Локальные классы

На практике чаще всего объявление происходит в методе некоторого другого класса.

Хотя объявлять локальный класс можно внутри статических и нестатических блоков инициализации.

Анонимные классы

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

Пример анонимного класса

new Thread(new Runnable() { public void run() { ... } }).start();

Синтаксис анонимного класса

Определение анонимного класса содержит:Оператор newИмя интерфейса для реализации или класса для наследования. Скобки, также как и при создании обычных объектов. Можно реализовать интерфейс или абстрактный класс.

Доступ к локальным переменным

Анонимный класс имеет доступ к полям внешнего класса.

Анонимный класс не имеет доступ локальным переменным области, в которой он определен, если они не финальные (final) или неизменяемые (effectively final).

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

Ограничения анонимных классов

Нельзя определять статические члены анонимного класса.

Анонимный класс может содержать статические поля, если это константы.

Анонимные классы также могут содержать в себе локальные классы. Конструктора в анонимном классе быть не может.

Использование final для классов

Класс с final не может подразделяться на подклассы. От такого класса нельзя наследоваться. Если класс объявлен final и abstract (взаимоисключающие понятия), произойдет ошибка компиляции 

Использование final для методов

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

Использование final для переменных

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

Вложенные интерфейсы

Интерфейс может быть объявлен членом класса или другого интерфейса. Такой интерфейс называется интерфейсом-членом или вложенным интерфейсом. Вложенный интерфейс может быть объявлен как public, private или protected.

Пример вложенного интерфейса

class A { interface B { void f(); } public class C implements B { public void f() {} } private class D implements B { public void f() {} }}

Вложенные в интерфейсы классы.

Вложенный (nested) в интерфейс класс является открытым (public) и статическим (static) даже без явного указания этих модификаторов. Помещая класс внутрь интерфейса, мы показываем, что он является неотъемлемой частью API этого интерфейса и более нигде не используется.

interface Colorable { public Color getColor(); public static class Color { private int red, green, blue; Color(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue; }

int getRed() { return red; } int getGreen() { return green; } int getBlue() { return blue; } } } class Triangle implements Colorable { private Color color; // ... @Override public Color getColor() { return color; } }

Использование

Colorable.Color color = new Colorable.Color(0, 0, 0); color = new Triangle.Color(255, 255, 255);

Recommended