Varje ny version av Java skiljer sig från de tidigare. Som ett exempel på en sådan förändring från material vi har täckt, hade språket inte enumsföre Java 5.
Standardmetoder i gränssnitt - 1
Bara så, Java 8 skiljer sig märkbart från Java 7. Vi kommer naturligtvis inte att ignorera viktiga innovationer. Eftersom vi pratar om gränssnitt i den här lektionen, låt oss överväga en uppdatering av språket: standardmetoder i gränssnitt . Du vet redan att ett gränssnitt inte implementerar beteende . Syftet är att beskriva vilket beteende som måste finnas i alla objekt som implementerar gränssnittet . Men utvecklare stötte ofta på situationer där implementeringen av en metod var densamma i alla klasser. Låt oss titta på vårt gamla bilexempel:
public interface Car {

   public void gas();

   public void brake();
}
public class Sedan implements Car {

   @Override
   public void gas() {
       System.out.println("Gas!");
   }

   @Override
   public void brake() {
       System.out.println("Brake!");
   }
}


public class Truck implements Car {

   @Override
   public void go() {
       System.out.println("Gas!");
   }

   @Override
   public void brake() {
       System.out.println("Brake!");
   }
}


public class F1Car implements Car {
   @Override
   public void go() {
       System.out.println("Gas!");
   }

   @Override
   public void brake() {
       System.out.println("Brake!");
   }
}
Vad tror du är huvudproblemet med den här koden? Du har säkert märkt att vi skrev en massa dubbletter av kod! Detta är ett vanligt problem inom programmering och det bör undvikas. Det är en annan sak att det inte fanns några särskilda lösningar före lanseringen av Java 8. När den versionen kom ut blev det möjligt att definiera standardmetoder och implementera dem direkt i ett gränssnitt! Så här gör du:
public interface Car {

   public default void gas() {
       System.out.println("Gas!");
   }

   public default void brake() {
       System.out.println("Brake!");
   }
}

public class Sedan implements Car {

}

public class Truck implements Car {

}

public class F1Car implements Car {

}
Nu har gas()och- brake()metoderna, som var desamma för alla bilar, flyttats in i gränssnittet, vilket eliminerar behovet av duplicerad kod. Och metoderna finns i var och en av klasserna!
public class Main {

   public static void main(String[] args) {

       F1Car f1Car = new F1Car();
       Sedan sedan = new Sedan();
       Truck truck = new Truck();
       truck.gas();
       sedan.gas();
       f1Car.brake();
   }
}
Vad händer om det finns 100 klasser med en gas()metod, men bara 99 av dem ska ha samma beteende? Förstör det allt? Fungerar inte en standardmetod i det här fallet? Naturligtvis inte :) Standardgränssnittsmetoder kan åsidosättas.
public class UnusualCar implements Car {
   @Override
   public void go() {
       System.out.println("This car accelerates differently!");
   }

   @Override
   public void brake() {
       System.out.println("This car slows down differently!");
   }
}
Alla de andra 99 typerna av bilar kommer att använda standardmetoden, medanUnusualCarklass är ett undantag. Utan att förstöra helheten kommer den lugnt att definiera sitt eget beteende. Flera arv i gränssnitt. Som du redan vet finns det inget multipelt arv i Java. Det finns många anledningar till detta. Vi kommer att överväga dem i detalj i en separat lektion. På andra språk, som C++, är situationen den omvända. Inget multipelt arv utgör en allvarlig utmaning, eftersom samma objekt kan ha flera olika egenskaper och beteenden. Till exempel är vi barn till våra föräldrar, elever till våra lärare och patienter till våra läkare. I det verkliga livet fyller vi olika roller och beter oss därför annorlunda: uppenbarligen interagerar vi med lärare annorlunda än med nära vänner. Låt oss försöka översätta denna situation till kod. Låt oss föreställa oss att vi har två klasser: damm och voljär. En damm behöver simfåglar, medan en voljär behöver flygande. För att representera detta skapade vi två basklasser:FlyingBirdoch Waterfowl.
public class Waterfowl {
}

public class FlyingBird {
}
Följaktligen kommer vi att skicka fåglar som ärver FlyingBirdtill voljären, medan de som kommer från Waterfowlkommer att gå till dammen. Allt verkar okomplicerat. Men vad ska vi göra om vi behöver definiera en anka någonstans? Ankor både simmar och flyger. Men vi har inget multipelarv. Lyckligtvis stöder Java flera implementeringar av gränssnitt. Om en klass inte kan ärva flera föräldrar är det enkelt att implementera flera gränssnitt! Vår anka kan vara en flygande fågel såväl som en simfågel :) För att uppnå önskat resultat behöver vi bara göra FlyingBirdoch Waterfowlgränssnitt snarare än klasser.
public class Duck implements FlyingBird, Waterfowl {

   // Methods of both interfaces combine easily into one class

   @Override
   public void fly() {
       System.out.println("Flying!");
   }

   @Override
   public void swim() {

       System.out.println("Swimming!");
   }
}
Detta innebär att vårt program behåller förmågan att flexibelt hantera klasser. När vi kombinerar det med standardmetoder blir vår förmåga att bestämma objekts beteende nästan obegränsad! :)