Abstracte klassen en Interfaces in C#

  1. Inleiding
  2. Class Library
  3. Abstracte klasse
  4. Interface
  5. Slot

Inleiding

In de eerdere posts over object oriëntatie zijn we uitgegaan van voorbeelden waarin een klasse (de child) erft van een base klasse (de parent). Klassen kunnen ook op Interfaces of Abstracte klassen gebaseerd zijn. Het is enigszins te vergelijken met met de taartvorm in de uitgelichte afbeelding. De taartvorm bepaalt de vorm voor het koekje, maar hoe dat koekje er verder uit komt te zien (hoe zoet?, wel geen chocolade er in? etc.) dat is aan jou.

Interfaces en Abstracte klassen hebben gemeenschappelijk dat zij gebruikt worden door andere klassen en niet naar een zelfstandig object geïnstantieerd kunnen worden, maar daar houdt de vergelijking ook mee op.

We zullen het één en ander weer toelichten aan de hand van de drie autofabrikanten die elkaar het leven zuur maken en alledrie geen boodschap hebben aan het milieu omdat dat alleen maar ten koste gaat van de winst.

up | down

Class Library

In het voorbeeld in deze post hebben we een class library gedefinieerd met de naam OverheidsRegulering. In de class library zetten we een abstracte klasse en een interface. De class library:

using System;
namespace OverheidsRegulering
{
 
 public abstract class Regelgeving
 {
  .
  // de abstracte klasse
  .
 }

 
 public interface IMarktwerking
 {
  .
  // de interface
  .
 }

}

Een link wordt gelegd naar Class Library OverheidsRegulering waarna de abstracte klasse en de interface verder worden geïmplementeerd.

using System;
using OverheidsRegulering;

namespace Implementaties
{
  //-------------------------------
  public class GHB: Regelgeving
  {
    .
    // implementeer de abstracte klasse
    .
  }
  //-------------------------------
  public class MGIM : IMarktwerking
  {
    .
    // implementeer de interface
    .
  }
 //-------------------------------
  class MainClass
  {
   public static void Main(string[] args)
   {
     .
     // instantieer object 
     . 
   }
  }

}

up | down

Abstracte Klasse

Inmiddels zijn een aantal maanden verstreken sinds de drie autofabrikanten (GHBGuanggongHunnenburgBetrieb, MGIMMigraine Imperialist Motors Corporation Groupe en XPAZXiaonlangPobedaAvtomobilnyZavod) hun nieuwe modellen hebben geïntroduceerd op de International Motor Show.

De nieuwe modellen zijn laaiend enthousiast ontvangen, de verkoopcijfers schieten omhoog (zelfs voor de kameraden van XPAZ) en de desbetreffende auto’s worden een prominent onderdeel van het straatbeeld.

Alledrie de fabrikanten beweren hoog bij laag dat hun auto’s een te verwaarlozen uitstoot hebben aan stikstofoxiden en fijnstof. Dit wordt echter door steeds meer mensen betwijfeld gezien het mistige straatbeeld (smog?) in de milieuzones en een toenemend aantal patiënten met klachten aan de luchtwegen.

De overheid gaat overstag na herhaaldelijk aandringen door de gezondheidszorg en aanhoudende druk van de milieulobby. Ze besluit het één en ander te reguleren en ze gaat een abstracte klasse maken. De overheid verplicht de autofabrikanten tot het gebruik van de abstracte klasse zodra de abstracte klasse is opgeleverd door het ICT ministerie:

 public abstract class Regelgeving
 {
  // Constructor - twee parameters zijn opgegeven
  public Regelgeving(string merk, int milieusticker)
  {
    _milieusticker = milieusticker;
    _merk = merk;
    _vervuilingsgraad = OverJeAuto(milieusticker);
    _milieumaatregel = GenomenMilieuMaatregel();
  }
  
  // Backing variables - fields
  private string _merk;
  private int _milieusticker;
  private string _vervuilingsgraad;
  private string _milieumaatregel;
 
  // Property Merk
  public string Merk
  {
   get { return _merk; }
   set { _merk = value; }
  }
  
  // Property MilieuSticker
  public int MilieuSticker
  {
   get { return _milieusticker; }
   set { _milieusticker = value; }
  }
  
  // Property Vervuilingsgraad
  public string Vervuilingsgraad
  {
   get { return _vervuilingsgraad; }
  }
 
  // Property MilieuMaatregel
  public string MilieuMaatregel
  {
  get { return _milieumaatregel; }
 }
 
 // Enumeratie
 enum Kleur
 { Groen,Paars,Geel,Oranje,Rood,Grijs }
 
 // Methode OverjeAuto
 public string OverJeAuto(int kleur)
 {
  string resultaat = "";
  switch (kleur)
  {
    case (int)Kleur.Groen:
         resultaat =
         "De milieuvriendelijkste.";
         break;
    case (int)Kleur.Paars:
         resultaat =
         "Iets onder de norm, maar voldoet.";
         break;
    case (int)Kleur.Geel:
         resultaat =
         "Iets ouder voertuig en 
         iets minder schoon.";
         break;
    case (int)Kleur.Oranje:
         resultaat =
         "Tamelijk oud voertuig en 
          relatief vervuilend.";
         break;
    case (int)Kleur.Rood:
         resultaat =
         "Zeer vervuilend!";
         break;
    case (int)Kleur.Grijs:
         resultaat =
         "Ultra vervuilend!!";
         break;
    default:
        resultaat =
        "Geen gegevens bekend.";
        break;
  }
  return resultaat;
 }

 public abstract string GenomenMilieuMaatregel();

}

De Regelgeving klasse is een abstracte klasse. Het is de bedoeling dat de abstracte klasse door andere klassen wordt gebruikt en een abstracte klasse kan niet naar een zelfstandig object geïnstantieerd worden.

Een kenmerk van de abstracte klasse is dat deze voorgedefineerde functionaliteit omvat. Zo is er de methode OverJeAuto() die in dit voorbeeld bewust niet virtual is. Dit om te voorkomen dat met deze methode wordt gesjoemeld middels een override. Meer over de virtual key word in de post over overriden.

Methode GenomenMilieuMaatregel() is een abstracte methode en de methode bevat verder geen functionaliteit. De klassen die gebruik gaan maken van de abstracte klasse moeten de abstracte methoden verplicht implementeren. In dit voorbeeld moeten de autofabrikanten verplicht aangeven welke milieumaatregelen zij genomen hebben en dat wordt afgedwongen door de verplichte implementatie van methode GenomenMileuMaatregel().

using System;
using OverheidsRegulering;

namespace Implementaties
{
 // Enumeratie
 enum Kleur { Groen, Paars, Geel, 
              Oranje, Rood, Grijs }
 
 public class GHB: Regelgeving
 {
   // Constructor
   public GHB(string merk, 
              int milieusticker) 
              : base(merk, milieusticker) { }

   // Deze methode moet verplicht
   // geïmplementeerd worden
   public override string GenomenMilieuMaatregel() {
          return "Betere roetfilters en 
                  aangepast motormanagement.";
   }
 }
 
 class MainClass
 {
   public static void Main(string[] args)
   {   
    // Instantieer
    GHB myGHB = 
    new GHB("GHB(GuanggongHunnenburgBetrieb)", 
    (int)Kleur.Paars);
    
    // Resultaat...
    Console.WriteLine("Gegevens van uw auto:");
    Console.WriteLine("- Merk: {0}",myGHB.Merk);
    
    Console.WriteLine("- Kleur milieusticker: {0}", 
    (Kleur)myGHB.MilieuSticker);
    Console.WriteLine("- Vervuilingsgraad: {0}", 
    myGHB.Vervuilingsgraad);
    
    Console.WriteLine(
    "- Genomen milieumaatregel: {0}\r\n", 
     myGHB.GenomenMilieuMaatregel());
   }
 }
}

Zo gezegd zo gedaan, de wetgeving wordt van kracht en de autofabrikanten moeten zich ernaar schikken met positieve gevolgen voor het milieu. Zo krijgt de auto van bijvoorbeeld autofabrikant GHB dankzij de verplicht te nemen milieumaatregelen een paarse milieusticker (was voorheen grijs) en ook is bekend wat GHB heeft gedaan om de uitstoot van stikstofoxiden en fijnstof te beperken:

Gegevens van uw auto:
- Merk: GHB(GuanggongHunnenburgBetrieb)
- Kleur milieusticker: Paars
- Vervuilingsgraad: Iets onder de norm, maar voldoet.
- Genomen milieumaatregel: 
  Betere roetfilters en aangepast motormanagement.

Press any key to continue...

up | down

Interface

De periodieke verkiezingen worden gehouden en een nieuwe regering komt aan de macht. Het milieu heeft voor de nieuwe regering geen prioriteit en de milieuwetten worden door de nieuwe regering afgeschaft. De nieuwe regering heeft de opvatting dat het milieu ook door marktwerking gereguleerd kan worden.

De abstracte klasse hoeft niet meer gebruikt te worden en de autofabrikanten mogen een interface gebruiken. interface IMarktwerking is een (kaal) raamwerk zonder enige functionaliteit en de interface mag naar eigen inzicht geïmplementeerd worden:

public interface IMarktwerking
{
  // Properties
  string Merk { get; set; }
  int MilieuSticker { get; set; }
  string Vervuilingsgraad { get; }
  string MilieuMaatregel { get; }
  
  // Methods
  string OverJeAuto(int kleur);
  string GenomenMilieuMaatregel();	
}

Autofabrikant MGIM implementeert als volgt de interface:

using System;
using OverheidsRegulering;
namespace Implementaties
{
 // Enumeratie
 enum Kleur
 {
  Groen, Paars, Geel, 
  Oranje, Rood, Grijs
 }

 public class MGIM : IMarktwerking
 {
  // Backing variables - fields
  private string _merk;
  private int _milieusticker;
  private string _vervuilingsgraad;
  private string _milieumaatregel;

  // Constructor - twee parameters zijn opgegeven
  public MGIM(string merk, int milieusticker)
  {
    _milieusticker = milieusticker;
    _merk = merk;
    _vervuilingsgraad = OverJeAuto(milieusticker);
    _milieumaatregel = GenomenMilieuMaatregel();
  }
  
  // Property Merk
  public string Merk
  {
    get { return _merk; }
    set { _merk = value; }
  }
  
  // Property MilieuSticker
  public int MilieuSticker
  {
    get { return _milieusticker; }
    set { _milieusticker = value; }
  }
  
  // Property Vervuilingsgraad
  public string Vervuilingsgraad
  {
    get { return _vervuilingsgraad; }
  }
    
  // Property MilieuMaatregel
  public string MilieuMaatregel
  {
    get { return _milieumaatregel; }
  }
   
  // die stomme milieumaatregelen
  // gaan alleen maar ten koste van 
  // de winst voor de aandeelhouders
  public string GenomenMilieuMaatregel()
  {
    return "Buzz off, 
            we have better things to do.";
  }
  
  // lekker belangrijk, wat interesseert
  // de milieusticker kleur en de 
  // vervuilingsgraad ons nou?
  public string OverJeAuto(int kleur) {
    return "The environment does not care us  
    what cares is you buying our cars.";
  }
 }

 class MainClass
 {
  public static void Main(string[] args)
  {   
    // Instantieer
    MGIM myMGIM = new MGIM(
    "MGIM(Migraine Imperialist Motors 
     Corporation Groupe)", 
    (int)Kleur.Grijs);
    Console.WriteLine("Gegevens van uw auto:");
    Console.WriteLine(
    "- Merk: {0}", myMGIM.Merk);
    Console.WriteLine(
    "- Kleur milieusticker: {0}", 
    (Kleur)myMGIM.MilieuSticker);
    Console.WriteLine(
    "- Vervuilingsgraad: {0}", 
    myMGIM.Vervuilingsgraad);
    Console.WriteLine(
    "- Genomen milieumaatregel: {0}", 
    myMGIM.GenomenMilieuMaatregel());
  }
 }
}

Met dit resultaat:

Gegevens van uw auto:
- Merk: MGIM(Migraine Imperialist 
  Motors Corporation Groupe)
- Kleur milieusticker: Grijs
- Vervuilingsgraad: 
  The environment does not care us 
  what cares is you buying our cars.
- Genomen milieumaatregel: 
  Buzz off, we have better things to do.

Press any key to continue...

De marktwerking heeft haar effect. De implementatie door MGIM vindt navolging bij andere autofabrikanten waardoor de milieustickers weer grijs worden, de winsten voor de aandeelhouders verbeteren doordat geld kostende milieumaatregelen niet meer genomen hoeven te worden en de milieuzones weer mistig (smog?) worden en de artsen weer meer patiënten krijgen met klachten aan de luchtwegen.

up | down

Slot

De basis van een klasse kan óf een andere klasse, óf een abstracte klasse, óf een interface zijn. Een interface is een kaal raamwerk en het wordt vaak beschouwd als een soort contract met vastgelegde onderdelen. De onderdelen van zo’n contract staan vast en alles moet geïmplementeerd worden, maar de implementatie mag wel weer naar eigen inzicht gedaan worden door de klasse die de interface gebruikt.

Een abstracte klasse lijkt enigszins op een interface, maar is dat niet. Een abstracte klasse kan voorgedefinieerde functionaliteiten bevatten welke de ervende klasse mag / moet overnemen. Tevens kan de abstracte klasse onderdelen bevatten zonder implementatie waarbij die onderdelen verplicht door de ervende klasse geïmplementeerd moeten worden.

We hebben het één en ander geïllustreerd met het voorbeeld van de drie autofabrikanten en de milieuwetgeving. De milieuwetgeving wordt aanvankelijk gehandhaafd middels abstracte klasse Regelgeving. De autofabrikanten worden verplicht tot het gebruik van de abstracte klasse waarbij ze methode GenomenMilieuMaatregel() verplicht moeten implementeren.

Het loslaten van de milieuwetten hebben we geïllustreerd met interface IMarktwerking. De marktwerking reguleert het milieu en in ons voorbeeld zorgt de marktwerking ervoor dat de auto’s juist meer stikstofoxiden en fijnstof gaan uitstoten omdat de autofabrikanten geen boodschap hebben aan het milieu en ze geen milieumaatregelen willen nemen omdat dat ten koste gaat van de winst. We zien dat ook terug in de implementatie van de interface, milieumaatregelen zijn voor de autofabrikanten geen aandachtspunten meer.

Hopelijk ben je met deze posting weer wat wijzer geworden en ik hoop je weer terug te zien in één van mijn volgende blog posts. Wil je weten wat ik nog meer over C# heb geschreven? Hit the C# button…

up


Laat een reactie achter

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *