Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az interfész definíciókat tartalmaz a nem absztrakt class vagy implementálandó kapcsolódó funkciók egy csoportjához struct . A felület definiálhat static metódusokat. A felület definiálhat egy alapértelmezett implementációt a tagok számára. A felület nem deklarálhat példányadatokat, például mezőket, automatikusan implementált tulajdonságokat vagy tulajdonságszerű eseményeket.
A felületek használatával például több forrásból származó viselkedést is belefoglalhat egy osztályba. Ez a képesség fontos a C#-ban, mert a nyelv nem támogatja az osztályok több öröklését. Emellett egy interfészt is használnia kell, ha a szerkezetek öröklését szeretné szimulálni, mert azok valójában nem örökölhetők egy másik struktúra vagy osztály alapján.
Az alábbi példa szerint a interface kulcsszóval definiálhat egy felületet.
interface IEquatable<T>
{
bool Equals(T obj);
}
Az illesztő nevének érvényes C# azonosítónévnek kell lennie. Konvenció szerint a felületnevek nagybetűvel Ikezdődnek.
Az interfészt megvalósító IEquatable<T> osztálynak vagy szerkezetnek tartalmaznia kell egy olyan metódus definícióját Equals , amely megfelel az interfész által megadott aláírásnak. Ennek eredményeképpen számíthat egy olyan típusosztályra T , amely olyan metódust implementál IEquatable<T>Equals , amellyel az osztály egy példánya meghatározhatja, hogy megegyezik-e ugyanannak az osztálynak egy másik példányával.
A definíció IEquatable<T> nem biztosít implementációt a következőhöz Equals: . Egy osztály vagy struktúra több interfészt is képes implementálni, de az osztály csak egyetlen osztálytól örökölhet.
Az absztrakt osztályokról további információt az Absztrakt és a Lezárt osztályok és osztálytagok című témakörben talál.
Az interfészek tartalmazhatnak példánymetasztereket, tulajdonságokat, eseményeket, indexelőket vagy a négy tagtípus bármilyen kombinációját. Az interfészek statikus konstruktorokat, mezőket, állandókat vagy operátorokat tartalmazhatnak. A nem mezőket tartalmazó illesztőtagok lehetnek static abstract. Az interfészek nem tartalmazhatnak példánymezőket, példánykonstruktorokat vagy véglegesítőket. A felület tagjai alapértelmezés szerint nyilvánosak, és explicit módon megadhatja az akadálymentességi módosítókat, például public, protected, internal, private, protected internalvagy private protected. A private tagoknak alapértelmezett implementációval kell rendelkezniük.
Ahhoz, hogy implicit implementációval implementáljon egy illesztőtagot, a implementálási osztály megfelelő tagjának nyilvánosnak, nem statikusnak kell lennie, és ugyanazzal a névvel és aláírással kell rendelkeznie, mint az interfész tagjának. Explicit felületi implementációt kell használnia az olyan felülettagok implementálásához, amelyek nem nyilvánosak.
Feljegyzés
Ha egy illesztő statikus tagokat deklarál, az azt megvalósító típus statikus tagokat is deklarálhat ugyanazzal az aláírással. Ezeket a tagokat a tagot deklaráló típus különbözteti meg és egyedileg azonosítja. A típusban deklarált statikus tag nem bírálja felül a felületen deklarált statikus tagot.
Az interfészt megvalósító osztálynak vagy szerkezetnek minden deklarált tag számára biztosítania kell egy implementációt anélkül, hogy az interfész által biztosított alapértelmezett implementációt biztosítanák. Ha azonban egy alaposztály implementál egy interfészt, az alaposztályból származtatott bármely osztály örökli ezt a megvalósítást.
Az alábbi példa a felület implementálását IEquatable<T> mutatja be. A végrehajtási osztálynak Carbiztosítania kell a módszer implementálását Equals .
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);
}
}
Az osztály tulajdonságai és indexelői további kiegészítőket határozhatnak meg egy felületen deklarált tulajdonsághoz vagy indexelőhöz. Egy felület például deklarálhat egy get kiegészítővel rendelkező tulajdonságot. Az interfészt megvalósító osztály ugyanazt a tulajdonságot deklarálhatja egy és egy get tartozék beállításával is. Ha azonban a tulajdonság vagy az indexelő explicit megvalósítást használ, a tartozéknak meg kell egyeznie. Az explicit implementációval kapcsolatos további információkért lásd az explicit felület implementálását és a felület tulajdonságait.
A felületek egy vagy több adaptertől örökölhetnek. A származtatott felület örökli a tagokat az alapfelületektől. A származtatott interfészt megvalósító osztálynak a származtatott felületen minden tagot implementálnia kell, beleértve a származtatott felület alapfelületeinek összes tagját is. Ez az osztály implicit módon konvertálható a származtatott felületre vagy annak bármely alapfelületére. Az osztályok tartalmazhatnak olyan interfészeket, amelyeket az általa öröklő alaposztályokon vagy más felületek által öröklő felületeken keresztül többször is használnak. Az osztály azonban csak egyszer és csak akkor biztosíthatja az illesztő implementálását, ha az osztály az osztály (class ClassName : InterfaceName) definíciójának részeként deklarálja a felületet. Ha a felület öröklődik, mert örökölt egy alaposztályt, amely implementálja az interfészt, az alaposztály biztosítja a felület tagjainak implementálását. A származtatott osztály azonban az örökölt implementáció helyett bármely virtuális felületi tagot átvehet. Amikor az interfészek egy metódus alapértelmezett implementációját deklarálják, az adott felületet implementáló osztály örökli ezt a megvalósítást (Az osztálypéldányt a felület típusára kell leadnia, hogy hozzáférjen az alapértelmezett implementációhoz a felülettagon).
Az alaposztályok virtuális tagok használatával is implementálhatnak felülettagokat. Ebben az esetben a származtatott osztály a virtuális tagok felülbírálásával módosíthatja az interfész viselkedését. A virtuális tagokkal kapcsolatos további információkért lásd a polimorfizmust.
Belső felületekkel való munka
A belső felület általában implicit implementációval valósítható meg a nyilvános tagokkal, feltéve, hogy a felületi aláírás összes típusa nyilvánosan elérhető. Ha azonban egy felület belső típusokat használ a tag-aláírásokban, az implicit megvalósítás lehetetlenné válik, mert a implementáló osztálytagnak nyilvánosnak kell lennie a belső típusok felfedése közben. Ilyen esetekben explicit felületi implementációt kell használnia.
Az alábbi példa mindkét forgatókönyvet mutatja be:
// Internal type that cannot be exposed publicly
internal class InternalConfiguration
{
public string Setting { get; set; } = "";
}
// Internal interface that CAN be implemented with public members
// because it only uses public types in its signature
internal interface ILoggable
{
void Log(string message); // string is public, so this works with implicit implementation
}
// Interface with internal accessibility using internal types
internal interface IConfigurable
{
void Configure(InternalConfiguration config); // Internal type prevents implicit implementation
}
// This class shows both implicit and explicit interface implementation
public class ServiceImplementation : ILoggable, IConfigurable
{
// Implicit implementation works for ILoggable because string is public
public void Log(string message)
{
Console.WriteLine($"Log: {message}");
}
// Explicit implementation required for IConfigurable because it uses internal types
void IConfigurable.Configure(InternalConfiguration config)
{
// Implementation here
Console.WriteLine($"Configured with: {config.Setting}");
}
// If we tried implicit implementation for IConfigurable, this wouldn't compile:
// public void Configure(InternalConfiguration config) // Error: cannot expose internal type
}
Az előző példában a IConfigurable felület egy belső típust InternalConfiguration használ a metódus-aláírásban. Az ServiceImplementation osztály nem használhat implicit implementációt, mert ehhez nyilvánossá kell tenni a Configure metódust, ami akkor nem engedélyezett, ha a metódus aláírása belső típusokat tartalmaz. Ehelyett explicit felületi implementációt használ, amely nem rendelkezik hozzáférés-módosítóval, és csak a felülettípuson keresztül érhető el.
Ezzel szemben a ILoggable felület implicit módon implementálható nyilvános tagokkal, mivel az aláírásában szereplő összes típus (string) nyilvánosan elérhető, még akkor is, ha maga a felület belső.
További információ az explicit felület implementálásáról: Explicit Interface Implementáció.
Interfészek összegzése
Az illesztő a következő tulajdonságokkal rendelkezik:
- A 8.0-nál korábbi C#-verziókban a felület olyan, mint egy absztrakt alaposztály, amely csak absztrakt tagokkal rendelkezik. Az interfészt megvalósító osztálynak vagy szerkezetnek minden tagját implementálnia kell.
- A C# 8.0-tól kezdődően egy felület definiálhatja az alapértelmezett implementációkat néhány vagy az összes tag számára. Az interfészt megvalósító osztálynak vagy szerkezetnek nem kell alapértelmezett implementációkkal rendelkező tagokat implementálnia. További információkért tekintse meg az alapértelmezett felületi metódusokat.
- A felület nem hozható létre közvetlenül.
- Egy osztály vagy szerkezet több interfészt is képes implementálni. Az osztály örökölhet egy alaposztályt, és egy vagy több interfészt is implementálhat.