Gå til innhold

Hva er egentlig poenget med interfaces?


Anbefalte innlegg

Dette er noe jeg aldri har blitt helt klok på.. Hva er poenget med interfaces?

Hvorfor gjøre:

interface A {
	void metode1();
	void metode2();
}

class Klasse implements A {

	@Override
	public void metode1() {
		// Gjør noe
		
	}

	@Override
	public void metode2() {
		// Gjør noe
	}
}

... i stedet for:

class Klasse {

	public void metode1() {
		// Gjør noe
	}

	public void metode2() {
		// Gjør noe
	}
}

? :)

Lenke til kommentar
Videoannonse
Annonse

Disclaimer: jeg er ikke noe god på java, og har absolutt ikke brukt eller lært om interfaces.

 

En java class kan implementere et hvilket som helst antall interfaces.

Og et hvilket som helst antall klasser kan implementere et interface.

Dette gir altså økt fleksibilitet.

 

interface storable_object
    public save_to_file(string filename);
    

class Document implements storable_object
    override save_to_file(string fn)
        openfile(fn)
        savestring(this.text)
        closefile()

class SettingsFileForDocument implements storable_object
    override save_to_file(string fn)
        openfile(fn)
        for each key in this.settings
            savestring(key + " = " + value)
        closefile()

class StyleFile implements storable_object
    override save_to_file(string fn)
        openfile(fn)
        savestring("Style: " + this.style_name)
        for each key in this.style
            savestring(key + " = " + value)
        closefile()
        
        
/* Og så magien */

storable_object obj;
obj = /* Og her kan du altså putte inn et object av hvilken som helst av klassene over */;
obj.save_to_file("test.txt")    
     
Lenke til kommentar

Kan ikke kalle en klasse metode på et instans av et interface så vidt jeg vet.

Dvs. jeg kan ikke gjøre følgende:

Interface1 test = new Klasse1();
test.metode1(); // Gir compiler error

Med en abstrakt klasse og arv så er saken annerledes.

AbstraktKlasse test = new Klasse1();
test.metode1();

Og en kan uansett gjøre:

Object test = new Klasse1();
((Klasse1) test).metode1();
Lenke til kommentar

Ikke noe ekspert selv, men vil si at Interfacer kan gi klasser visse egenskaper.

 

Personlig så tenker jeg å extende en klasse vil si at klassen er en form for det du extender, men da med litt flere/spesifikke egenskaper.

Ønsker du å gi klassen din flere egenskaper, så implementerer du interfaces.

 

F.eks. se på klassen ArrayList:

public class ArrayList<E>extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, Serializable

Den extender AbstractList, men den implementerer flere interfaces for å få de egenskapene. Siden den implementerer interfacesene ovenfor, så vet vi hvilke egenskaper de har, og kan kalle metoder som finnes i dem. Og siden alle list-klasser implementerer List, kan vi si List<T> someList = new .... på alle typer implementasjoner av list.

Ønsker du å lage en egen versjon av liste, så er det bare å implementere List, implementere metodene i List, og eventuelt implementere flere interfaces om du ønsker flere egenskaper.

 

Som sagt ingen ekspert selv, og bruker interfaces sjelden, men er hvertfall slik jeg tenker.

Finnes garantert mange sider som forklarer det mye bedre enn meg ved et kjapt google-søk.

Endret av Fred7555
Lenke til kommentar

Et interface en god måte å streamline koden din på. Hvis du lager et rollespill "The Garbage Collectors" og du vil ha en drøss av våpen, så har du et interface som heter "Weapon". Bruker du dette interfacet på klassen "Axe", "Bow" og "Machete" så kan du garantere at disse objektene følger interfacet, så da vet du at klasser som implementer Weapon kan bruke .attack(), .drop() osv. Dette er også betryggende når du skal mikse og matche forskjellige objekter og iterere over de, for da vet du at når du itererer over alle våpnene dine at du kan kalle f.eks .drop() på de. Hva .drop() gjør med de forskjellige objektene er opp til hver enkel klasse.

Endret av Gavekort
Lenke til kommentar

Jeg var vel inne på dette med å kunne garantere konsistens innenfor objektene. Om du ender opp med en haug av våpen som mangler grunnlegende metoder så kan du ikke kalle f.eks .drop() uten å først undersøke at du faktisk har laget en drop-metode i alle våpnene dine. Tar du alle objektene dine som implementerer Weapon så kan du iterere over .drop().

Lenke til kommentar

Det er ikke helt åpenbart hva forskjellen mellom en abstrakt klasse og et interface er. Konseptuelt er de veldig like - man kan ikke instansiere kun hverken en abstrakt klasse eller et interface, så man lar andre klasser arve fra eller implementere dem. I Java kommer den første forskjellen her: klasser kan bare extende en annen klasse, men de kan implementere så mange de vill. Derfor er det vanlig å la abstrakte klasser bestemme hva en klasse er, mens interfaces bestemmer hva en klasse gjør.

 

Fordelen med alt dette er, nettopp som du sier, at man (ofte) slipper instanceof og casting. La oss si du har en liste med ting som skal lagres. Alle klassene du har vil kanskje ta seg av skrivingen selv, da det kan være forskjellige formater de lagres i etc. Her kan det være en god idé å ha et interface Saveable, som har en funksjon, save(), som du kaller for at objektet skal lagre seg selv. Koden din kan da se litt ut som dette:

for (Saveable item : listeMedItems) {
    item.save(filePath);
}

Siden vi vet at alle elementene implementerer Saveable, og at Saveable har en funksjon som heter save(), så kan vi garantere at dette vil gå bra. I tillegg har vi ikke brukt arv, så klassene kan arve hva de vil, uavhengig av hverandre.

  • Liker 4
Lenke til kommentar

En viktig ting man bruker interface til er lyttere som skal få beskjed når visse deler av objectet endrer seg:

Interface Observable{
    public void addListener(Observer o);
}
Interface Observer{
   public void somethingChanged(Observable o);
}
Class A implements Observable{
ArrayList<Observer> listeners;

public void metode(){
     fireSomethingChanged()
}
public void fireSomethingChanged(){
      for(listener in listeners){
            listener.somethingChanged(this)
}public void addListener(Obsever o){
    listener.add(o);
}

Alle typer object kan lytte så lenge det implementerer Observer interfacet. For each løkker i java bruker på en måte interface også , alle klasser som implementerer iterable interfacet ( må ha metoden public Iterator iterator() ) kan brukes i for each løkker. Samme med comparable interfacet som gjør at man kan bruke innebygde sort metoden i java API-et. Man kan altså tilby funskjon til kode som enda ikke er laget fordi man garanterer hva metodene vil hete, hva de returnerer og hva de tar inn.

Endret av tusseladdden
Lenke til kommentar
  • 5 uker senere...

Her var det mye rart. Hovedgrunnen til å bruke et interface er at man kan har en kontrakt, som viser hva klasser som implementerer interfacet tar imot og gir i fra seg.

 

Da kan du byttet ut implementasjonen av interfacet dersom krav som ikke utgjør en betydning for signaturen forandrer seg.

 

Gitt dette interfacet:

public interface AccountService {

    public Optional<Account> findByUsername(String username);

}

Gitt denne implementasjonen:

public class AccountServiceImpl implements AccountService {

    @Override
    public Optional<Account> findByUsername(String username) {
        return accountRepository.findByUsername(username);
    }
}

Nå, tenk om du i fremtiden ikke har accountRepository og må gjøre noe annet for å returnere Optional<Account>? Det kan du, siden klassene dine implementerer interfacet og ikke en faktisk implementasjon, er det ikke nøye hva som skjer i @Override methoden, så lenge den ikke bryter kontrakten til interfacet.

  • Liker 1
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...