Interfaces : gedrag definiëren voor meerdere typen

Een interface bevat definities voor een groep gerelateerde functies die een niet-abstracte of een struct niet-abstracte class moet implementeren. Een interface kan methoden definiëren static die een implementatie moeten hebben. Een interface kan een standaard implementatie definiëren voor leden. Een interface declareert mogelijk geen exemplaargegevens, zoals velden, automatisch geïmplementeerde eigenschappen of eigenschapsachtige gebeurtenissen.

Met behulp van interfaces kunt u bijvoorbeeld gedrag uit meerdere bronnen in een klasse opnemen. Deze mogelijkheid is belangrijk in C# omdat de taal geen ondersteuning biedt voor meerdere overnames van klassen. Bovendien moet u een interface gebruiken als u overname voor structs wilt simuleren, omdat ze niet daadwerkelijk kunnen overnemen van een andere struct of klasse.

U definieert een interface met behulp van het interface trefwoord zoals in het volgende voorbeeld wordt weergegeven.

interface IEquatable<T>
{
    bool Equals(T obj);
}

De naam van een interface moet een geldige C# -id-naam zijn. Standaard beginnen interfacenamen met een hoofdletter I.

Elke klasse of struct die de IEquatable<T> interface implementeert, moet een definitie bevatten voor een Equals methode die overeenkomt met de handtekening die door de interface wordt opgegeven. Als gevolg hiervan kunt u rekenen op een klasse die wordt geïmplementeerd IEquatable<T> om een Equals methode te bevatten waarmee een exemplaar van de klasse kan bepalen of deze gelijk is aan een ander exemplaar van dezelfde klasse.

De definitie van IEquatable<T> deze definitie biedt geen implementatie voor Equals. Een klasse of struct kan meerdere interfaces implementeren, maar een klasse kan slechts overnemen van één klasse.

Zie Abstracte en Verzegelde klassen en Klasseleden voor meer informatie over abstracte klassen.

Interfaces kunnen exemplaarmethoden, eigenschappen, gebeurtenissen, indexeerfuncties of een combinatie van deze vier lidtypen bevatten. Interfaces kunnen statische constructors, velden, constanten of operators bevatten. Vanaf C# 11 zijn interfaceleden die geen velden zijn static abstractmogelijk. Een interface kan geen exemplaarvelden, instantieconstructors of finalizers bevatten. Interfaceleden zijn standaard openbaar en u kunt expliciet toegankelijkheidsaanpassingen opgeven, zoals , , , , private, of private protectedprotected internal. internalprotectedpublic Een private lid moet een standaard implementatie hebben.

Als u een interfacelid wilt implementeren, moet het bijbehorende lid van de implementatieklasse openbaar, niet-statisch zijn en dezelfde naam en handtekening hebben als het interfacelid.

Notitie

Wanneer een interface statische leden declareert, kan een type implementatie van die interface ook statische leden met dezelfde handtekening declareren. Deze zijn uniek en uniek geïdentificeerd door het type dat het lid declareren. Het statische lid dat in een type is gedeclareerd, overschrijft niet het statische lid dat in de interface is gedeclareerd.

Een klasse of struct die een interface implementeert, moet een implementatie bieden voor alle gedeclareerde leden zonder standaard implementatie die door de interface wordt geleverd. Als een basisklasse echter een interface implementeert, neemt elke klasse die is afgeleid van de basisklasse die implementatie over.

In het volgende voorbeeld ziet u een implementatie van de IEquatable<T> interface. De implementatieklasse, Carmoet een implementatie van de Equals methode bieden.

public class Car : IEquatable<Car>
{
    public string? Make { get; set; }
    public string? Model { get; set; }
    public string? Year { get; set; }

    // Implementation of IEquatable<T> interface
    public bool Equals(Car? car)
    {
        return (this.Make, this.Model, this.Year) ==
            (car?.Make, car?.Model, car?.Year);
    }
}

Eigenschappen en indexeerfuncties van een klasse kunnen extra accessors definiëren voor een eigenschap of indexeerfunctie die is gedefinieerd in een interface. Een interface kan bijvoorbeeld een eigenschap declareren die een get accessor heeft. De klasse die de interface implementeert, kan dezelfde eigenschap declareren met zowel een getals een instellende accessor. Als de eigenschap of indexeerfunctie echter gebruikmaakt van expliciete implementatie, moeten de accessors overeenkomen. Zie Expliciete interface-implementatie - en interface-eigenschappen voor meer informatie over expliciete implementatie.

Interfaces kunnen overnemen van een of meer interfaces. De afgeleide interface neemt de leden over van de basisinterfaces. Een klasse die een afgeleide interface implementeert, moet alle leden in de afgeleide interface implementeren, inclusief alle leden van de basisinterfaces van de afgeleide interface. Deze klasse kan impliciet worden geconverteerd naar de afgeleide interface of een van de basisinterfaces. Een klasse kan meerdere keren een interface bevatten via basisklassen die worden overgenomen of via interfaces die andere interfaces overnemen. De klasse kan echter slechts één keer een interface implementeren en alleen als de klasse de interface declareert als onderdeel van de definitie van de klasse (class ClassName : InterfaceName). Als de interface wordt overgenomen omdat u een basisklasse hebt overgenomen die de interface implementeert, biedt de basisklasse de implementatie van de leden van de interface. De afgeleide klasse kan echter alle leden van de virtuele interface opnieuw implementeren in plaats van de overgenomen implementatie te gebruiken. Wanneer interfaces een standaard implementatie van een methode declareren, neemt elke klasse die die interface implementeert die implementatie over (U moet het klasse-exemplaar naar het interfacetype casten om toegang te krijgen tot de standaard implementatie op het interfacelid).

Een basisklasse kan ook interfaceleden implementeren met behulp van virtuele leden. In dat geval kan een afgeleide klasse het gedrag van de interface wijzigen door de virtuele leden te overschrijven. Zie Polymorfisme voor meer informatie over virtuele leden.

Overzicht van interfaces

Een interface heeft de volgende eigenschappen:

  • In C#-versies ouder dan 8.0 is een interface als een abstracte basisklasse met alleen abstracte leden. Een klasse of struct die de interface implementeert, moet alle leden ervan implementeren.
  • Vanaf C# 8.0 kan een interface standaard implementaties definiëren voor sommige of alle leden. Een klasse of struct die de interface implementeert, hoeft geen leden met standaard implementaties te implementeren. Zie de standaardinterfacemethoden voor meer informatie.
  • Een interface kan niet rechtstreeks worden geïnstantieerd. De leden worden geïmplementeerd door elke klasse of struct die de interface implementeert.
  • Een klasse of struct kan meerdere interfaces implementeren. Een klasse kan een basisklasse overnemen en ook een of meer interfaces implementeren.