Programmering

Hvornår skal man bruge en abstrakt klasse vs. interface i C #

Når du designer applikationer, er det vigtigt at vide, hvornår man skal bruge en abstrakt klasse, og hvornår man skal bruge en grænseflade. Selvom abstrakte klasser og grænseflader på nogle måder ser ud til at være ens, er der vigtige forskelle, der bestemmer, hvilket er det bedste valg for det, du prøver at opnå. I dette blogindlæg vil jeg diskutere disse forskelle, og hvordan man beslutter, hvornår man skal bruge hvilke.

Det korte svar: En abstrakt klasse giver dig mulighed for at oprette funktionalitet, som underklasser kan implementere eller tilsidesætte. En grænseflade giver dig kun mulighed for at definere funktionalitet, ikke implementere den. Og mens en klasse kun kan udvide en abstrakt klasse, kan den drage fordel af flere grænseflader.

C # abstrakt klasse forklaret

En abstrakt klasse er en speciel type klasse, der ikke kan instantieres. En abstrakt klasse er designet til at blive arvet af underklasser, der enten implementerer eller tilsidesætter dens metoder. Med andre ord er abstrakte klasser enten delvist implementeret eller slet ikke implementeret. Du kan have funktionalitet i din abstrakte klasse - metoderne i en abstrakt klasse kan være både abstrakte og konkrete. En abstrakt klasse kan have konstruktører - dette er en stor forskel mellem en abstrakt klasse og en grænseflade. Du kan drage fordel af abstrakte klasser til at designe komponenter og angive et niveau af fælles funktionalitet, der skal implementeres af afledte klasser.

C # interface forklaret

En grænseflade er dybest set en kontrakt - den har ingen implementering. En grænseflade kan kun indeholde metodedeklarationer; det kan ikke indeholde metodedefinitioner. Du kan heller ikke have nogen medlemsdata i en grænseflade. Mens en abstrakt klasse kan indeholde metodedefinitioner, felter og konstruktører, kan en grænseflade kun have erklæringer om begivenheder, metoder og egenskaber. Metoder, der er angivet i en grænseflade, skal implementeres af de klasser, der implementerer grænsefladen. Bemærk, at en klasse kan implementere mere end en grænseflade, men kun udvide en klasse. Den klasse, der implementerer grænsefladen, skal implementere alle dens medlemmer. Som en abstrakt klasse kan en grænseflade ikke instantieres.

Skal jeg bruge en abstrakt klasse eller en grænseflade?

Abstrakte klasser giver dig fleksibiliteten til at have bestemte konkrete metoder og nogle andre metoder, som de afledte klasser skal implementere. Hvis du derimod bruger grænseflader, skal du implementere alle metoderne i klassen, der udvider grænsefladen. En abstrakt klasse er et godt valg, hvis du har planer om fremtidig ekspansion - dvs. hvis en fremtidig ekspansion sandsynligvis er i klassehierarkiet. Hvis du vil yde support til fremtidig udvidelse, når du bruger grænseflader, skal du udvide grænsefladen og oprette en ny.

På en anden note er det let at tilføje en ny grænseflade til hierarkiet, hvis det er nødvendigt. Men hvis du allerede har en abstrakt klasse i dit hierarki, kan du ikke tilføje en anden - dvs. du kan kun tilføje en abstrakt klasse, hvis ingen er tilgængelige. Du skal bruge en grænseflade, hvis du vil have en kontrakt om en eller anden adfærd eller funktionalitet. Du skal ikke bruge en grænseflade, hvis du har brug for at skrive den samme kode til grænseflademetoderne. I dette tilfælde skal du bruge en abstrakt klasse, definere metoden en gang og genbruge den efter behov. Brug grænseflader til at afkoble din applikations kode fra specifikke implementeringer af den eller for at begrænse adgangen til medlemmer af en bestemt type.

Som Microsofts dokumentation af grænseflader siger:

Ved at bruge grænseflader kan du for eksempel inkludere adfærd fra flere kilder i en klasse. Denne kapacitet er vigtig i C #, fordi sproget ikke understøtter flere arv af klasser. Derudover skal du bruge en grænseflade, hvis du vil simulere arv til strukturer, fordi de faktisk ikke kan arve fra en anden struktur eller klasse.

Implicitte og eksplicitte interfaceimplementeringer

Grænseflader kan implementeres implicit eller eksplicit. Lad mig forklare, hvordan disse to implementeringer adskiller sig. Overvej en grænseflade kaldet IBusinessLogic.

offentlig grænseflade IBusinessLogic

{

ugyld Initialiser ();

}

Den følgende klasse navngivet BusinessLogic implementerer IBusinessLogic interface.

offentlig klasse BusinessLogic: IBusinessLogic

{

offentlig ugyldighed Initialiser ()

   {

// Noget kode

   }

}

Du kan oprette en forekomst af BusinessLogic klasse eksplicit og derefter ringe til Initialiser () metode som vist nedenfor.

 IBusinessLogic businessLogic = ny BusinessLogic ();

businessLogic.Initialize ();

Følgende kodestykke illustrerer, hvordan du kan implementere IBusinessLogic interface implicit.

offentlig klasse BusinessLogic: IBusinessLogic

{

ugyldig IBusinessLogic.Initialize ()

   {

   }

}

Du kan nu påberåbe dig Initialiser () metode på samme måde ved hjælp af en henvisning til IBusinessLogic interface. Forskellen i de to tilgange er, at når du implementerer grænsefladen eksplicit i din klasse, er du tvunget til at påkalde en metode til din grænseflade ved kun at bruge en henvisning til grænsefladen. Derfor fungerer følgende kodestykke ikke, dvs. kompilerer ikke.

 BusinessLogic businessLogic = ny BusinessLogic ();

businessLogic.Initialize ();

Sådan gør du mere i C #:

  • Hvornår skal man bruge en abstrakt klasse vs. interface i C #
  • Sådan arbejder du med AutoMapper i C #
  • Sådan bruges lambda-udtryk i C #
  • Sådan arbejder du med Action-, Func- og Predicate-delegerede i C #
  • Sådan arbejder du med delegerede i C #
  • Sådan implementeres en simpel logger i C #
  • Sådan arbejder du med attributter i C #
  • Sådan arbejder du med log4net i C #
  • Sådan implementeres depotdesignmønsteret i C #
  • Sådan arbejder du med refleksion i C #
  • Sådan arbejder du med filsystemwatcher i C #
  • Sådan udføres doven initialisering i C #
  • Sådan arbejder du med MSMQ i C #
  • Sådan arbejder du med udvidelsesmetoder i C #
  • Hvordan vi lambda-udtryk i C #
  • Hvornår skal du bruge det flygtige nøgleord i C #
  • Sådan bruges afkastnøgleordet i C #
  • Sådan implementeres polymorfisme i C #
  • Sådan bygger du din egen opgaveplanlægning i C #
  • Sådan arbejder du med RabbitMQ i C #
  • Sådan arbejder du med en tuple i C #
  • Udforskning af virtuelle og abstrakte metoder i C #
$config[zx-auto] not found$config[zx-overlay] not found