Sintaxa:
[public] interface NumeInterfata
[extends ListaInterfete]
{
// declarații de membri de interfață
}
De exemplu:
interface Animal {
void maninca();
void doarme();
}
Reguli de lucru cu interfețele în Java:
- Numele interfeței nu coincide cu numele altei clase sau interfeţe din acelaşi pachet.
- Dacă declarația unei interfeţe conţine clauza extends atunci interfața va moșteni toate metodele şi constantele interfețelor enumerate în <ListaInterfete>, care se numesc superinterfeţe.
- Nu există o superinterfaţă generală cum este clasa Object pentru superclase.
- Corpul unei metode într-o interfață este ;, dar începând cu Java 8, în interfață pot fi metode static și default.
- Toți membri interfeței sunt considerați implicit public, dar dacă modificatorul public este specificat atunci sunt accesibili şi înafara pachetului.
- Deoarece variabilele unei interfeţe sunt considerate constante acestea trebuie să fie inițializate altfel se va produce eroare de compilare.
- Metode cu aceeași semnătură, dar tip de return diferit nu pot fi folosite în interfeţe.
- Variabilele unei interfeţe sunt considerate implicit public static final. Chiar dacă veți omite aceste cuvinte rezervate vor fi adăugate în mod automat de compilatorul Java la faza de compilare, în fișierul *.class.
- E posibil ca o clasă să folosească variabilele cu același nume dintr-o altă interfață, în acest caz la accesarea acestora trebuie de respectat sintaxa: numeInterfata.numeVariabila
- La declararea unei metode nu este permisă apariția tuturor modificatorilor de acces, doar public sau abstract.
- Dacă o clasă implementează 2 interfețe ce au metodă cu același nume este de ajuns să implementăm o singură metodă.
- Nu este binevenit de a folosi metode cu același nume într-o interfață sau mai multe interfeţe să conțină metode cu acelaşi nume.
- Interfețele nu au câmpuri și nici constructori. Nu pot fi insanțiate, și nu pot păstra starea obiectelor.
class numeClasa implements Interfata1,...,InterfataN { ...
}
De exemplu:
class Cal implements Animal{void manica(){...}void doarme(){...}}
Reguli:

interface Poligon {
- O clasă poate implementa orice număr de interfețe.
- Clasa ce implementează interfața trebuie obligatoriu să conțină cod pentru toate metodele interfeței, din acest motiv o interfață implementată într-o clasă nu trebuie modificată, dacă modificăm interfața obligatoriu modificăm şi codul sursă al clasei ce o implementează.
interface A {
// membrii interfeței A
}
interface B {
// membrii interfeței B
}
class C implements A, B {
// implementarea metodelor abstracte din A// implementarea metodelor abstracte din B
}
- O interfață poate extinde altă interfață:
interface A {
// membrii interfeței A
}interface B extends A {
// membrii interfeței B
}class C implements B {
// implementarea metodelor abstracte din A// implementarea metodelor abstracte din B
}
- O interfață poate extinde mai multe interfețe:
interface A {
// membrii interfeței A
}interface B {
// membrii interfeței B
}interface C extends A, B {
// membrii interfeței C
}class D implements C {
// implementarea metodelor abstracte din A// implementarea metodelor abstracte din B// implementarea metodelor abstracte din C
}
- Clasa ce implementează o interfață poate avea şi metode specifice ei, nu doar metodele interfeței.
- O interfață poate extinde o altă interfață, dar nu o poate implementa.
Exemplul 1 Elaborați un program în Java care definește o interfață Poligon cu metoda getAria, utilizând parametri variabili pentru calculul ariei. Implementați această interfață în clasele Dreptunghi și Patrat, astfel încât programul principal să calculeze și să afișeze aria pentru fiecare formă geometrică.
interface Poligon {
void getAria(int ... laturi);
}
class Dreptunghi implements Poligon {
public void getAria(int ... laturi) {
class Dreptunghi implements Poligon {
public void getAria(int ... laturi) {
if (laturi.length==2)System.out.println("Aria dreptunghiului este " + (laturi[0] * laturi[1]));
}}
class Patrat implements Poligon {
class Patrat implements Poligon {
public void getAria(int ... laturi) {if (laturi.length==1) System.out.println("Aria patratului este "+(Math.pow(laturi[0], 2)));
}}
class Main {
public static void main(String[] args) {
class Main {
public static void main(String[] args) {
Dreptunghi r1 = new Dreptunghi ();r1.getAria(5, 6);Patrat p1 = new Patrat();p1.getAria(5);
În Java nu poate fi implementată moștenirea multiplă la nivel de stare, dar interfețele permit realizarea moștenirii multiple la nivel de comportament. Atunci când o clasă implementează mai multe interfețe, sau o interfață extinde mai multe interfețe spunem că simulăm moștenirea multiplă în Java.
Exemplul 2 Elaborați un program în Java care definește două interfețe, Masina și Autobus, fiecare conținând câte o constantă și o metodă abstractă. Implementați aceste interfețe într-o clasă Vehicul, astfel încât programul principal să calculeze și să afișeze distanța parcursă și viteza.
interface Masina{
int viteza=90;
public void distanta();
}
interface Autobus{
int distanta=100;
public void viteza();
}
class Vehicul implements Masina,Autobus {
public void distanta(){
int distanta=viteza*100;
System.out.println("Distanta parcursa este "+distanta);
}
public void viteza(){
int viteza=distanta/100;
System.out.println("Viteza = "+viteza);
}}
class DemoVehicule{
public static void main(String args[]){
System.out.println("Vehicul");
Vehicul v1=new Vehicul();
v1.distanta();
v1.viteza();
}}
Exemplu 3 Elaborați un program în Java care definește o interfață Interfata_1 și o interfață Interfata_2 care o extinde, adăugând o metodă suplimentară. Implementați aceste interfețe într-o clasă DemoInterfete, astfel încât programul principal să demonstreze apelul metodelor definite.
interface Interfata_1{
public void metoda_1();
}
interface Interfata_2 extends Interfata_1 {
interface Interfata_2 extends Interfata_1 {
public void metoda_2();
}
class DemoInterfete implements Interfata_2{
class DemoInterfete implements Interfata_2{
public void metoda_1(){System.out.println("Aici metoda 1");
}
public void metoda_2(){
public void metoda_2(){
System.out.println("Aici metoda 2");
}
public static void main(String args[]){
public static void main(String args[]){
DemoInterfete obj = new DemoInterfete();obj.metoda_2(); }}
Notă! Interfețele nu pot fi instanțiate însă putem crea variabile referință de tip interfață. De exemplu, dacă în metoda main() în exemplul de mai sus vom folosi construcția:
public static void main(String args[]){Interfata_2 obj = new DemoInterfete();obj.metoda_2(); }
Aceasta este validă, iar programul va afișa același rezultat. Vor putea fi apelate pentru obiectul obj acele metode din Interfata_2 care au implementare în clasa dată. Variabilele referință de tip interfață se folosesc doar urmate de instanţierea clasei ce implementează interfața la care face referință variabila.
Începând cu versiunea Java 8 este permis ca în interfețe să fie definite metode statice și/sau default după sintaxa:
public interface InterfataMea {
void metodaClasica();default void metodaDefault() {
System.out.println(”metoda default!”);
}static void metodaStatica(){
System.out.println(”metoda static!”);
}}
Reguli de reținut:
- Atât metodele default, cât și metodele static în interfață trebuie să conțină corp.
- Metodele statice:
- pot fi accesate direct, respectând sintaxa: InterfațaMea.metodaStatica()
- aparțin în exclusivitate interfețelor, nu pot fi accesate de instanțele claselor care vor implementa interfața
- clasele care vor implementa interfața nu vor putea supradefini așa tip de metodă
- clasele care vor implementa interfața vor avea posibilitatea să conțină metodă cu același nume ca și metoda statică.
- Metodele default:
- nu pot fi accesate direct
- clasele care vor implementa interfața are dreptul să supradefinească așa tip de metodă
- permit modificarea interfețelor fără a afecta clasele care deja au implementat interfața
- atunci când extinzi o interfață de către altă interfață care are o metoda default, poți face una din următoarele acțiuni:
- să nu o menționezi, ceea ce înseamnă că o moștenești așa cum e de la interfața;
- să o redeclari, ceea ce o face de tip abstract, iar clasele care vor implementa interfața, vor adăuga o altă implementare a acestei metode;
- să o redefinești, ceea ce o suprascrie pe cea originală, cu o implementare default diferită.
- metode statice: există dreptul de a nu defini o clasă separată pentru o metodă utilitară.
- metode default: există posibilitatea de a defini o funcționalitate comună pentru toate clasele care vor implementa interfața.
public interface Vehicul {
String getBrand();
String speedUp();
String slowDown();
default String turnAlarmOn() {
return "Alarmă conectată”;
}
default String turnAlarmOff() {
return "Alarma deconectata";
}}
public class Masina implements Vehicul {
private String brand;
Masina(String nume){
brand=nume;
}
@Override
public String getBrand() {
return brand;
}
@Override
public String speedUp() {
return "Masina accelereaza";
}
@Override
public String slowDown() {
return "Masina incetineste";
} }
public class TestMasina {
public static void main(String[] args) {
Vehicul car = new Masina("BMW");
System.out.println(car.getBrand());
System.out.println(car.speedUp());
System.out.println(car.slowDown());
System.out.println(car.turnAlarmOn());
System.out.println(car.turnAlarmOff()); }}

Pentru a distinge corect între utilizarea claselor abstracte sau interfețe luați în considerare următoarele aspecte:
String getBrand();
String speedUp();
String slowDown();
default String turnAlarmOn() {
return "Alarmă conectată”;
}
default String turnAlarmOff() {
return "Alarma deconectata";
}}
public class Masina implements Vehicul {
private String brand;
Masina(String nume){
brand=nume;
}
@Override
public String getBrand() {
return brand;
}
@Override
public String speedUp() {
return "Masina accelereaza";
}
@Override
public String slowDown() {
return "Masina incetineste";
} }
public class TestMasina {
public static void main(String[] args) {
Vehicul car = new Masina("BMW");
System.out.println(car.getBrand());
System.out.println(car.speedUp());
System.out.println(car.slowDown());
System.out.println(car.turnAlarmOn());
System.out.println(car.turnAlarmOff()); }}
Pentru a distinge corect între utilizarea claselor abstracte sau interfețe luați în considerare următoarele aspecte:
- Dacă aveți nevoie să descrieți doar comportamentul obiectelor, nu și starea acestora utilizați interfețe. În caz contrar clase abstracte, deoarece clasele abstracte includ atât starea cât și comportamentul obiectelor. O interfață descrie doar comportamentul.
- Dacă aveți nevoie să specificați un comportament comun pentru mai multe clase care fac parte din ierarhii diferite utilizați interfețe. De exemplu clasele Om și Masina, nu au nimic comun, fac parte din ierarhii diferite, dar au comun faptul că se deplasează: omul cu picioarele, iar mașina cu ajutorul componentelor tehnice. Deci, o clasă abstractă conectează clase care sunt foarte strâns legate. În timp ce interfața poate fi implementată de clase care nu au absolut nimic în comun.
- Java suportă moștenirea de stare, la nivel de clasă, și moștenire de comportament, la nivel de interfață. Clasele pot implementa orice număr de interfețe, dar pot moșteni o singură clasă. Deci dacă doriți să implementați moștenirea de stare, unde o clasă derivată (subclasă) primește atât comportamentul (metodele) cât și starea (atributele) din clasa de bază (superclasă), utilizați clase sau clase abstracte. Dar dacă doriți să specificați un contract sau specificații de comportament, fără a furniza o implementare implicită atunci utilizați interfețele.
- Explicați conceptul de interfață în Java și modul în care este utilizată pentru a defini comportamente standard și contracte pentru clasele care o implementează.
- Comparați clasele abstracte și interfețele în ceea ce privește caracteristicile, utilizările și restricțiile lor în Java.
- Argumentați beneficiile și avantajele utilizării interfețelor în comparație cu clasele abstracte în diverse scenarii de proiectare și dezvoltare a software-ului.
- Care este diferența între o interfață și o clasă abstractă în ceea ce privește implementarea metodelor?
Vă doresc o zi deosebit de frumoasă! ❤️
