Java тело метода интерфейса

Java тело метода интерфейса

+ статья в копилке. Но у меня есть вопрос: что будет если класс реализует 2 интерфейса, но у этих двух существует одинаковые методы?

А если в двух интерфейсах будет дефолтный метод с одинаковой сигнатурой, что тогда? Получаем проблему множественного наследования?

«Без множественного наследования возникает серьезная проблема: у одного и того же объекта может быть ряд разных характеристик и «поведений»». Не понял, может наоборот с множественным наследованием??

Жесть какая, но зачем. Нужны методы с каким-то поведением по-умолчанию — ну реализуй абстрактный класс. В java нет множественного наследования, но есть вот такие вот «поделки» в его сторону. По факту даю 146% что ни к чему хорошему в больших проектах это не приведет, просто даст новичкам больше свободы в написании говнокода.

Окей, а что случится, если мы реализуем в классе два интерфейса, но оба имеют дефолтный метод с одинаковым именем? Будет конфликт?

т.е. создать два обычных класса и если надо от них наследоваться писать implements a не extends? в самом классе писать вместо класс interface или не надо

JavaRush — это интерактивный онлайн-курс по изучению Java-программирования c нуля. Он содержит 1200 практических задач с проверкой решения в один клик, необходимый минимум теории по основам Java и мотивирующие фишки, которые помогут пройти курс до конца: игры, опросы, интересные проекты и статьи об эффективном обучении и карьере Java‑девелопера.

Этот веб-сайт использует данные cookie, чтобы настроить персонально под вас работу сервиса. Используя веб-сайт, вы даете согласие на применение данных cookie. Больше подробностей — в нашем Пользовательском соглашении.

Читайте также:  Полное и неполное ветвление в питоне

Источник

Java тело метода интерфейса

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

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

Чтобы определить интерфейс, используется ключевое слово interface . Например:

Данный интерфейс называется Printable. Интерфейс может определять константы и методы, которые могут иметь, а могут и не иметь реализации. Методы без реализации похожи на абстрактные методы абстрактных классов. Так, в данном случае объявлен один метод, который не имеет реализации.

Все методы интерфейса не имеют модификаторов доступа, но фактически по умолчанию доступ public , так как цель интерфейса — определение функционала для реализации его классом. Поэтому весь функционал должен быть открыт для реализации.

Чтобы класс применил интерфейс, надо использовать ключевое слово implements :

public class Program < public static void main(String[] args) < Book b1 = new Book("Java. Complete Referense.", "H. Shildt"); b1.print(); >> interface Printable < void print(); >class Book implements Printable < String name; String author; Book(String name, String author)< this.name = name; this.author = author; >public void print() < System.out.printf("%s (%s) \n", name, author); >>

В данном случае класс Book реализует интерфейс Printable. При этом надо учитывать, что если класс применяет интерфейс, то он должен реализовать все методы интерфейса, как в случае выше реализован метод print . Потом в методе main мы можем создать объект класса Book и вызвать его метод print. Если класс не реализует какие-то методы интерфейса, то такой класс должен быть определен как абстрактный, а его неабстрактные классы-наследники затем должны будут реализовать эти методы.

В тоже время мы не можем напрямую создавать объекты интерфейсов, поэтому следующий код не будет работать:

Printable pr = new Printable(); pr.print();

Одним из преимуществ использования интерфейсов является то, что они позволяют добавить в приложение гибкости. Например, в дополнение к классу Book определим еще один класс, который будет реализовывать интерфейс Printable:

class Journal implements Printable < private String name; String getName()< return name; >Journal(String name) < this.name = name; >public void print() < System.out.println(name); >>

Класс Book и класс Journal связаны тем, что они реализуют интерфейс Printable. Поэтому мы динамически в программе можем создавать объекты Printable как экземпляры обоих классов:

public class Program < public static void main(String[] args) < Printable printable = new Book("Java. Complete Reference", "H. Shildt"); printable.print(); // Java. Complete Reference (H. Shildt) printable = new Journal("Foreign Policy"); printable.print(); // Foreign Policy >> interface Printable < void print(); >class Book implements Printable < String name; String author; Book(String name, String author)< this.name = name; this.author = author; >public void print() < System.out.printf("%s (%s) \n", name, author); >> class Journal implements Printable < private String name; String getName()< return name; >Journal(String name) < this.name = name; >public void print() < System.out.println(name); >>

Интерфейсы в преобразованиях типов

Все сказанное в отношении преобразования типов характерно и для интерфейсов. Например, так как класс Journal реализует интерфейс Printable, то переменная типа Printable может хранить ссылку на объект типа Journal:

Printable p =new Journal("Foreign Affairs"); p.print(); // Интерфейс не имеет метода getName, необходимо явное приведение String name = ((Journal)p).getName(); System.out.println(name);

И если мы хотим обратиться к методам класса Journal, которые определены не в интерфейсе Printable, а в самом классе Journal, то нам надо явным образом выполнить преобразование типов: ((Journal)p).getName();

Методы по умолчанию

Ранее до JDK 8 при реализации интерфейса мы должны были обязательно реализовать все его методы в классе. А сам интерфейс мог содержать только определения методов без конкретной реализации. В JDK 8 была добавлена такая функциональность как методы по умолчанию . И теперь интерфейсы кроме определения методов могут иметь их реализацию по умолчанию, которая используется, если класс, реализующий данный интерфейс, не реализует метод. Например, создадим метод по умолчанию в интерфейсе Printable:

Метод по умолчанию — это обычный метод без модификаторов, который помечается ключевым словом default . Затем в классе Journal нам необязательно этот метод реализовать, хотя мы можем его и переопределить:

class Journal implements Printable < private String name; String getName()< return name; >Journal(String name) < this.name = name; >>

Статические методы

Начиная с JDK 8 в интерфейсах доступны статические методы — они аналогичны методам класса:

Чтобы обратиться к статическому методу интерфейса также, как и в случае с классами, пишут название интерфейса и метод:

public static void main(String[] args)

Приватные методы

По умолчанию все методы в интерфейсе фактически имеют модификатор public. Однако начиная с Java 9 мы также можем определять в интерфейсе методы с модификатором private . Они могут быть статическими и нестатическими, но они не могут иметь реализации по умолчанию.

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

public class Program < public static void main(String[] args) < Calculatable c = new Calculation(); System.out.println(c.sum(1, 2)); System.out.println(c.sum(1, 2, 4)); >> class Calculation implements Calculatable < >interface Calculatable < default int sum(int a, int b)< return sumAll(a, b); >default int sum(int a, int b, int c) < return sumAll(a, b, c); >private int sumAll(int. values) < int result = 0; for(int n : values)< result += n; >return result; > >

Константы в интерфейсах

Кроме методов в интерфейсах могут быть определены статические константы:

Хотя такие константы также не имеют модификаторов, но по умолчанию они имеют модификатор доступа public static final , и поэтому их значение доступно из любого места программы.

public class Program < public static void main(String[] args) < WaterPipe pipe = new WaterPipe(); pipe.printState(1); >> class WaterPipe implements Stateable < public void printState(int n)< if(n==OPEN) System.out.println("Water is opened"); else if(n==CLOSED) System.out.println("Water is closed"); else System.out.println("State is invalid"); >> interface Stateable

Множественная реализация интерфейсов

Если нам надо применить в классе несколько интерфейсов, то они все перечисляются через запятую после слова implements:

interface Printable < // методы интерфейса >interface Searchable < // методы интерфейса >class Book implements Printable, Searchable < // реализация класса >

Наследование интерфейсов

Интерфейсы, как и классы, могут наследоваться:

interface BookPrintable extends Printable

При применении этого интерфейса класс Book должен будет реализовать как методы интерфейса BookPrintable, так и методы базового интерфейса Printable.

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

Как и классы, интерфейсы могут быть вложенными, то есть могут быть определены в классах или других интерфейсах. Например:

При применении такого интерфейса нам надо указывать его полное имя вместе с именем класса:

public class Journal implements Printer.Printable < String name; Journal(String name)< this.name = name; >public void print() < System.out.println(name); >>

Использование интерфейса будет аналогично предыдущим случаям:

Printer.Printable p =new Journal("Foreign Affairs"); p.print();

Интерфейсы как параметры и результаты методов

И также как и в случае с классами, интерфейсы могут использоваться в качестве типа параметров метода или в качестве возвращаемого типа:

public class Program < public static void main(String[] args) < Printable printable = createPrintable("Foreign Affairs",false); printable.print(); read(new Book("Java for impatients", "Cay Horstmann")); read(new Journal("Java Dayly News")); >static void read(Printable p) < p.print(); >static Printable createPrintable(String name, boolean option) < if(option) return new Book(name, "Undefined"); else return new Journal(name); >> interface Printable < void print(); >class Book implements Printable < String name; String author; Book(String name, String author)< this.name = name; this.author = author; >public void print() < System.out.printf("%s (%s) \n", name, author); >> class Journal implements Printable < private String name; String getName()< return name; >Journal(String name) < this.name = name; >public void print() < System.out.println(name); >>

Метод read() в качестве параметра принимает объект интерфейса Printable, поэтому в этот метод мы можем передать как объект Book, так и объект Journal.

Метод createPrintable() возвращает объект Printable, поэтому также мы можем возвратить как объект Book, так и Journal.

Foreign Affairs Java for impatients (Cay Horstmann) Java Dayly News

Источник

Оцените статью