Statiske og standardmetoder i grensesnitt i Java

1. Oversikt

Java 8 brakte til bordet noen få nye funksjoner, inkludert lambda-uttrykk, funksjonelle grensesnitt, metodereferanser, strømmer, valgfritt og statisk og misligholde metoder i grensesnitt.

Noen av dem er allerede dekket i denne artikkelen. Ikke desto mindre, statisk og misligholde metoder i grensesnitt fortjener et dypere blikk alene.

I denne artikkelen vil vi diskutere i dybden hvordan å bruke statisk og misligholde metoder i grensesnitt og gå gjennom noen brukstilfeller der de kan være nyttige.

2. Hvorfor standardmetoder i grensesnitt er nødvendig

Som vanlige grensesnittmetoder, standardmetoder er implisitt offentlige - det er ikke nødvendig å spesifisere offentlig modifikator.

I motsetning til vanlige grensesnittmetoder, er de det erklært med misligholde nøkkelord i begynnelsen av metodesignaturen, og de gi en implementering.

La oss se et enkelt eksempel:

offentlig grensesnitt MyInterface {// vanlige grensesnittmetoder standard ugyldig defaultMethod () {// standard implementeringsmetode}}

Grunnen til misligholde metoder ble inkludert i Java 8-utgivelsen er ganske opplagt.

I en typisk design basert på abstraksjoner, der et grensesnitt har en eller flere implementeringer, hvis en eller flere metoder legges til grensesnittet, vil alle implementeringene bli tvunget til å implementere dem også. Ellers vil designet bare bryte sammen.

Standardgrensesnittmetoder er en effektiv måte å håndtere dette problemet på. De la oss legge til nye metoder i et grensesnitt som automatisk er tilgjengelig i implementeringene. Dermed er det ikke nødvendig å endre implementeringsklassene.

På denne måten, bakoverkompatibilitet er pent bevart uten å måtte refaktorere implementeringene.

3. Standard grensesnittmetoder i aksjon

For bedre å forstå funksjonaliteten til misligholde grensesnittmetoder, la oss lage et enkelt eksempel.

Si at vi har en naiv Kjøretøy grensesnitt og bare én implementering. Det kan være mer, men la oss holde det så enkelt:

offentlig grensesnitt Vehicle {String getBrand (); Streng speedUp (); String slowDown (); standard String turnAlarmOn () {return "Slå kjøretøyalarmen på."; } standard String turnAlarmOff () {retur "Slå av kjøretøyalarmen."; }}

Og la oss skrive implementeringsklassen:

offentlig klasse Bilredskaper Vehicle {private String brand; // constructors / getters @Override public String getBrand () {returmerke; } @ Override public String speedUp () {return "Bilen farter fort."; } @ Override public String slowDown () {retur "Bilen bremser."; }} 

Til slutt, la oss definere en typisk hoved- klasse, som skaper en forekomst av Bil og kaller metodene:

public static void main (String [] args) {Vehicle car = new Car ("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 ()); }

Vær oppmerksom på hvordan misligholde metoder turnAlarmOn () og turnAlarmOff () fra vår Kjøretøy grensesnitt er automatisk tilgjengelig i Bil klasse.

Videre, hvis vi på et eller annet tidspunkt bestemmer oss for å legge til flere misligholde metoder for å Kjøretøy grensesnitt, vil applikasjonen fortsatt jobbe, og vi trenger ikke å tvinge klassen til å tilby implementeringer for de nye metodene.

Den mest typiske bruken av standardmetoder i grensesnitt er å gradvis gi tilleggsfunksjonalitet til en gitt type uten å bryte ned implementeringsklassene.

I tillegg kan de brukes til gi tilleggsfunksjonalitet rundt en eksisterende abstrakt metode:

offentlig grensesnitt Vehicle {// tilleggsgrensesnittmetoder dobbelt getSpeed ​​(); standard dobbelt getSpeedInKMH (dobbel hastighet) {// konvertering}}

4. Flere arvregler

Standard grensesnittmetoder er en ganske fin funksjon, men med noen advarsler verdt å nevne. Siden Java tillater klasser å implementere flere grensesnitt, er det viktig å vite hva skjer når en klasse implementerer flere grensesnitt som definerer det samme misligholde metoder.

For å bedre forstå dette scenariet, la oss definere et nytt Alarm grensesnitt og refaktor Bil klasse:

offentlig grensesnitt Alarm {standard String turnAlarmOn () {return "Slå alarmen på."; } standard String turnAlarmOff () {return "Slå av alarmen."; }}

Med dette nye grensesnittet som definerer sitt eget sett med misligholde metoder, Bil klasse ville implementere begge deler Kjøretøy og Alarm:

offentlig klasse Bilredskaper Kjøretøy, alarm {// ...}

I dette tilfellet, koden vil ganske enkelt ikke kompilere, da det er en konflikt forårsaket av arv med flere grensesnitt (aka diamantproblemet). De Bil klasse ville arve begge sett med misligholde metoder. Hvilke skal man hete da?

For å løse denne tvetydigheten må vi eksplisitt gi en implementering av metodene:

@Override public String turnAlarmOn () {// tilpasset implementering} @Override public String turnAlarmOff () {// tilpasset implementering}

Vi kan også har klassen vår bruke misligholde metoder for et av grensesnittene.

La oss se et eksempel som bruker misligholde metoder fra Kjøretøy grensesnitt:

@ Override public String turnAlarmOn () {return Vehicle.super.turnAlarmOn (); } @ Override public String turnAlarmOff () {return Vehicle.super.turnAlarmOff (); } 

På samme måte kan vi få klassen til å bruke misligholde metoder definert i Alarm grensesnitt:

@ Override public String turnAlarmOn () {return Alarm.super.turnAlarmOn (); } @ Override public String turnAlarmOff () {return Alarm.super.turnAlarmOff (); } 

Videre er det jevnt mulig å gjøre Bil klasse bruker begge settene med standardmetoder:

@Override public String turnAlarmOn () {return Vehicle.super.turnAlarmOn () + "" + Alarm.super.turnAlarmOn (); } @ Override public String turnAlarmOff () {return Vehicle.super.turnAlarmOff () + "" + Alarm.super.turnAlarmOff (); } 

5. Statiske grensesnittmetoder

Bortsett fra å kunne erklære misligholde metoder i grensesnitt, Java 8 lar oss definere og implementere statisk metoder i grensesnitt.

Siden statisk metoder hører ikke til et bestemt objekt, de er ikke en del av API for klassene som implementerer grensesnittet, og de må være det kalt ved å bruke grensesnittnavnet foran metodenavnet.

For å forstå hvordan statisk metoder fungerer i grensesnitt, la oss omformere Kjøretøy grensesnitt og legge til det a statisk verktøymetode:

offentlig grensesnitt Kjøretøy {// vanlig / standard grensesnittmetoder statisk int getHorsePower (int rpm, int moment) {retur (rpm * moment) / 5252; }} 

Definere en statisk metoden i et grensesnitt er identisk med å definere en i en klasse. Videre, a statisk metoden kan påberopes innen andre statisk og misligholde metoder.

Si nå at vi ønsker å beregne hestekrefter til et bestemt kjøretøys motor. Vi bare kaller getHorsePower () metode:

Vehicle.getHorsePower (2500, 480)); 

Ideen bak statisk grensesnittmetoder er å gi en enkel mekanisme som lar oss øke samholdsgraden av et design ved å sette sammen relaterte metoder på ett sted uten å måtte lage et objekt.

Mer eller mindre det samme kan gjøres med abstrakte klasser. Hovedforskjellen ligger i at abstrakte klasser kan ha konstruktører, tilstand og oppførsel.

Videre gjør statiske metoder i grensesnitt mulig å gruppere relaterte verktøymetoder, uten å måtte lage kunstige nytteklasser som bare er plassholdere for statiske metoder.

6. Konklusjon

I denne artikkelen undersøkte vi grundig bruken av statisk og misligholde grensesnittmetoder i Java 8. Ved første øyekast kan denne funksjonen se litt slurvete ut, spesielt sett fra et objektorientert puristisk perspektiv. Ideelt sett bør grensesnitt ikke innkapsle atferd og skal bare brukes til å definere den offentlige API-en av en bestemt type.

Når det gjelder å opprettholde bakoverkompatibilitet med eksisterende kode, statisk og misligholde metoder er en god kompromiss.

Og som vanlig er alle kodeeksemplene vist i denne artikkelen tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found