Java интерфейси, обяснени с примери

Интерфейси

Интерфейсът в Java е малко като Class, но със значителна разлика: един interfaceможе да има само подписи на методи, полета и методи по подразбиране. От Java 8 можете да създавате и методи по подразбиране. В следващия блок можете да видите пример за интерфейс:

public interface Vehicle { public String licensePlate = ""; public float maxVel public void start(); public void stop(); default void blowHorn(){ System.out.println("Blowing horn"); } }

Интерфейсът по-горе съдържа две полета, два метода и метод по подразбиране. Сам по себе си не е от голяма полза, но те обикновено се използват заедно с класовете. Как Просто, трябва да се уверите, че някой implementsго е клас .

public class Car implements Vehicle { public void start() { System.out.println("starting engine..."); } public void stop() { System.out.println("stopping engine..."); } }

Сега има основно правило : Класът трябва да реализира всички методи в интерфейса. Методите трябва да имат точно същия подпис (име, параметри и изключения), както е описано в интерфейса. Класът не трябва да декларира полетата, а само методите.

Екземпляри на интерфейс

След като създадете Java клас, който и да implementsе интерфейс, екземплярът на обекта може да бъде посочен като екземпляр на интерфейса. Тази концепция е подобна на концепцията за създаване на наследство.

// following our previous example Vehicle tesla = new Car(); tesla.start(); // starting engine ...

Интерфейсът не може да съдържа методи на конструктор. Следователно не можете да създадете екземпляр на самия интерфейс. Трябва да създадете екземпляр на някакъв клас, изпълняващ интерфейс, за да го препратите.

Помислете за интерфейсите като за празен формуляр за договор или за шаблон.

Какво можете да направите с тази функция? Полиморфизъм! Можете да използвате само интерфейси за препращане към екземпляри на обекти!

class Truck implements Vehicle { public void start() { System.out.println("starting truck engine..."); } public void stop() { System.out.println("stopping truck engine..."); } } class Starter { // static method, can be called without instantiating the class public static void startEngine(Vehicle vehicle) { vehicle.start(); } } Vehicle tesla = new Car(); Vehicle tata = new Truck(); Starter.startEngine(tesla); // starting engine ... Starter.startEngine(tata); // starting truck engine ...

Но какво ще кажете за множество интерфейси?

Да, можете да внедрите множество интерфейси в един клас. Докато в наследяването в рамките на класове сте били ограничени да наследявате само един клас, тук можете да разширите произволен брой интерфейси. Но не забравяйте да приложите всички методи на всички интерфейси, в противен случай компилацията ще се провали!

public interface GPS { public void getCoordinates(); } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } }

Някои функции на интерфейсите

  • Можете да поставите променливи в интерфейса, въпреки че това няма да бъде разумно решение, тъй като класовете не са длъжни да имат същата променлива. Накратко, избягвайте поставянето на променливи!
  • Всички променливи и методи в интерфейса са публични, дори ако оставите publicключовата дума.
  • Интерфейсът не може да посочи изпълнението на определен метод. От класовете зависи да го направят. Въпреки че наскоро имаше изключение (виж по-долу).
  • Ако клас реализира множество интерфейси, тогава има отдалечен шанс за припокриване на подпис на метод. Тъй като Java не позволява множество методи за точно един и същ подпис, това може да доведе до проблеми. Вижте този въпрос за повече информация.

Методи по подразбиране на интерфейса

Преди Java 8 нямахме начин да насочим интерфейс, за да имаме конкретен метод за изпълнение. Това води до много объркване и прекъсвания на кода, ако дефиницията на интерфейса внезапно бъде променена.

Да предположим, че сте написали библиотека с отворен код, която съдържа интерфейс. Да кажем, че вашите клиенти, т.е. практически всички разработчици по света, го използват силно и са доволни. Сега трябваше да надстроите библиотеката, като добавите нова дефиниция на метода към интерфейса, за да поддържате нова функция. Но това би нарушило всички компилации, тъй като всички класове, изпълняващи този интерфейс, трябва да се променят сега. Каква катастрофа!

За щастие Java 8 вече ни предоставя defaultметоди за интерфейси. А defaultметод може да съдържа своя собствена изпълнение директно в интерфейса! Така че, ако клас не реализира метод по подразбиране, компилаторът ще вземе изпълнението, споменато в интерфейса. Хубаво, нали? Така че във вашата библиотека можете да добавяте произволен брой методи по подразбиране в интерфейсите, без да се страхувате да счупите нещо!

public interface GPS { public void getCoordinates(); default public void getRoughCoordinates() { // implementation to return coordinates from rough sources // such as wifi & mobile System.out.println("Fetching rough coordinates..."); } } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } // no implementation of getRoughCoordinates() } Smartphone motoG = new Smartphone(); motog.getRoughCoordinates(); // Fetching rough coordinates...

Но какво се случва, ако два интерфейса имат един и същ подпис на метод?

Страхотен въпрос. В този случай, ако не предоставите изпълнението в класа, лошият компилатор ще се обърка и просто ще се провали! Трябва да осигурите изпълнение на метод по подразбиране и в класа. Съществува и чудесен начин superда се обадите коя реализация ви харесва:

public interface Radio { // public void startRadio(); // public void stopRadio(); default public void next() { System.out.println("Next from Radio"); } } public interface MusicPlayer { // public void start(); // public void pause(); // public void stop(); default public void next() { System.out.println("Next from MusicPlayer"); } } public class Smartphone implements Radio, MusicPlayer { public void next() { // Suppose you want to call MusicPlayer next MusicPlayer.super.next(); } } Smartphone motoG = new Smartphone(); motoG.next(); // Next from MusicPlayer

Статични методи в интерфейсите

Също така ново за Java 8 е възможността за добавяне на статични методи към интерфейсите. Статичните методи в интерфейсите са почти идентични със статичните методи в конкретни класове. Единствената голяма разлика е, че staticметодите не се наследяват в класовете, които реализират интерфейса. Това означава, че интерфейсът се препраща при извикване на статичния метод, а не на класа, който го реализира.

interface MusicPlayer { public static void commercial(String sponsor) { System.out.println("Now for a message brought to you by " + sponsor); } public void play(); } class Smartphone implements MusicPlayer { public void play() { System.out.println("Playing from smartphone"); } } class Main { public static void main(String[] args) { Smartphone motoG = new Smartphone(); MusicPlayer.commercial("Motorola"); // Called on interface not on implementing class // motoG.commercial("Motorola"); // This would cause a compilation error } }

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

Възможно е също така в Java интерфейс да наследи друг интерфейс, като използвате, познахте, extendsключова дума:

public interface Player { public void start(); public void pause(); public void stop(); } public interface MusicPlayer extends Player { default public void next() { System.out.println("Next from MusicPlayer"); } }

Това означава, че MusicPlayerинтерфейсът за изпълнение на класа трябва да прилага всички методи, MusicPlayerкакто и Player:

public class SmartPhone implements MusicPlayer { public void start() { System.out.println("start"); } public void stop() { System.out.println("stop"); } public void pause() { System.out.println("pause"); } }

Така че сега имате добро разбиране на Java интерфейсите! Отидете да научите за абстрактните класове, за да видите как Java ви дава още един начин за дефиниране на договори.