Java Basics: Абстракции

Абстракции

Необходимо обязательно следить за доступами! У interface доступы к методам всегда public, а в классе, реализующем может быть не указан модификатор доступа, который по умолчанию = default package-private. Это приведет к ошибке:

1
2
3
4
5
6
7
public interface X {
void do();
}

public class Y implements X {
void do() { } // ошибка в связи с понижением доступа с public на package-private
}

Реализация методов

Необходимо следить за возвращаемыми типами:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface X {
int do();
}

interface Y {
String do();
}

class Z implements X, Y {...} // ошибка, т.к. методы do имеют несовместимые типы

interface Y2 {
Number do();
}

class Z implements X, Y2 {} // ошибка, см. выше

interface X2 {
Integer do();
}

class ImplOk implements X2, Y2 {
public Integer do() {}
}

Класс ImplOk определен корректно, т.к. Integer наследуется от Number, а как отмечалось ранее, на уточнение класса при возврате из метода, компилятор реагирует без ошибок.

Type-cast

Как отмечалось ранее, type-cast класса в может быть с ошибкой компиляции, если классы никак не связаны между собой (это касается и instanceof):

1
2
Number x = 1;
if(x instanceof String) // ошибка компиляции - String никак не связан с Number

Но для интерфейсов данное правило не работает:

1
2
Number x = 1;
if(x instanceof List) // ок, но всегда будет false

Указанное выше правило не работает в случае классов, помеченных как final

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class X extends Number {}
public class Y implements List {}
public final class Z extends Number {}

X x = new X();
if(x instanceof List) // допустимо, т.к. List - интерфейс
if(x instanceof String) // ошибка компиляции - нет связанности
if(x instanceof Integer) // ошибка компиляции - нет связанности

Y y = new Y();
if(y instanceof Number) // ошибка компиляции - нет связанности

Z z = new Z();
if(z instanceof List) // ошибка компиляции. Хоть List и интерфейс, но класс объявлен как final

Interface методы

Interface default-метод

  • может применяться только к методам интерфейса;
  • должен иметь тело метода;
  • должен быть public;
  • не может быть abstract, final или static;
  • может быть переопределен в реализации;
  • если класс наследуется от 2 интерфейсов с default маркерами, то метод необходимо будет переопределять (возможно, вызов конкретной реализации в любом из интерфейсов).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface FaceA {
public default int get() {
return 1;
}
}

public interface FaceB {
public default int get() {
return 2;
}
}

public class Impl implements FaceA, FaceB {
@Override
public int get() {
int a = IFace.super.get();
int b = FaceI.super.get();
return a + b;
}
}

Такое же правило касается и наследования одним интерфейсом других - несколько default методов необходимо свести в одну единую реализацию метода.

Interface static-метод

  • может не указывать модификатор доступа - тогда он будет public. Если указывать, то доступен только public;
  • если метод имеет static, значит должен иметь тело метода;
  • не может быть final или abstract;
  • не может быть переопределен;
  • при обращении может быть использовано только имя данного интерфейса (не наследников).
1
2
3
public interface X {
static void do() {...}
}

Interface private-метод

  • должен содержать тело;
  • может быть использован только default и private (но не private static) методами того же интерфейса:
1
2
3
4
5
6
7
public interface X {
default void go() {
doGo();
}

private void doGo() { ... }
}

Поскольку метод не будет виден классами, реализующими интерфейс, данные методы очень удобны когда необходимо ограничить видимость метода, но при этом, распространить его действие на все реализующие классы.

Interface private-static-метод

  • должен содержать тело;
  • могут быть вызваны любым методом, но только в рамках этого интерфейса.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface X {
public static void method1() {
doGo();
}

default void go() {
doGo();
}

private void method2() {
doGo();
}

private static void doGo() {
...
}
}
 Comments
Comment plugin failed to load
Loading comment plugin