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.
Jótanács
Új szoftverfejlesztés? Először az Első lépések oktatóanyagokkal kezdje. Miután meg kell határoznia a megosztott viselkedést a nem kapcsolódó típusok között, felületekkel fog találkozni.
Tapasztalt egy másik nyelven? A C# interfészek hasonlóak a Swift Java vagy protokolljaihoz. A C#-specifikus minták explicit implementálási szakaszának lefuttatása.
Az interfész egy szerződést határoz meg: olyan kapcsolódó metódusok, tulajdonságok, események és indexelők csoportja, amelyeket class implementálnia kell vagy struct végre kell hajtania. Az interfészek lehetővé teszik, hogy egy típus több szerződést implementáljon, ami azért fontos, mert a C# nem támogatja az osztályok több öröklését. A szerkezetek nem öröklődhetnek más szerkezetektől vagy osztályoktól, ezért az interfészek az egyetlen módja annak, hogy megosztott viselkedést adjanak a strustruktúratípusokhoz.
Az alábbi példa egy felületet és egy azt megvalósító osztályt deklarál:
interface IEquatable<T>
{
bool Equals(T obj);
}
public class Car : IEquatable<Car>
{
public string? Make { get; set; }
public string? Model { get; set; }
public string? Year { get; set; }
public bool Equals(Car? car) =>
car is not null &&
(Make, Model, Year) == (car.Make, car.Model, car.Year);
}
Minden implementálandó IEquatable<T> osztálynak vagy szerkezetnek meg kell adnia a Equals felületi aláírásnak megfelelő metódust. Bármilyen IEquatable<T> megvalósításra számíthat az egyenlőség összehasonlításának támogatása érdekében, függetlenül a konkrét típustól. Ez a kiszámíthatóság az interfészek alapvető értéke.
Felület deklarálása
Adjon meg egy felületet a interface kulcsszóval. Konvenció szerint a felületnevek nagybetűvel Ikezdődnek:
interface ILogger
{
void Log(string message);
string Name { get; }
}
A felületek metódusokat, tulajdonságokat, eseményeket és indexelőket tartalmazhatnak. Az interfészek nem tartalmazhatnak példánymezőket, példánykonstruktorokat vagy véglegesítőket. Tagok alapértelmezés szerint public állapotban vannak. Szükség esetén más akadálymentességi módosítókat is megadhat. Például olyan tagokhoz használja a internal elemet, amelyeknek nem szabad az összeállításon kívül látszani.
Felület implementálása
Egy osztály vagy strustruktúra felsorolja azokat a felületeket, amelyek implementálva lesznek a kettőspont után a deklarációban. Az osztálynak implementációt kell biztosítania a felületen deklarált minden tag számára:
public class ConsoleLogger : ILogger
{
public string Name => "Console";
public void Log(string message) =>
Console.WriteLine($"[{Name}] {message}");
}
public class FileLogger : ILogger
{
public string Name => "File";
public void Log(string message)
{
// In a real app, write to a file
Console.WriteLine($"[{Name}] Writing to file: {message}");
}
}
Egy osztály több interfészt is képes implementálni, vesszővel elválasztva. Minden felsorolt felület minden tagja számára implementációkat kell biztosítania.
Explicit megvalósítás
Néha úgy kell implementálnia egy felülettagot, hogy az ne váljon az osztály nyilvános API-jának részévé. Az explicit implementáció az interfész nevével minősíti a tagot. A tag csak a felülettípus változója révén érhető el:
interface IMetric
{
double GetDistance(); // Returns meters
}
interface IImperial
{
double GetDistance(); // Returns feet
}
public class Runway(double meters) : IMetric, IImperial
{
// Explicit implementation for IMetric
double IMetric.GetDistance() => meters;
// Explicit implementation for IImperial
double IImperial.GetDistance() => meters * 3.28084;
}
Az explicit megvalósítás akkor hasznos, ha két felület azonos nevű tagokat deklarál, vagy ha az osztály nyilvános felületét tisztán szeretné tartani. További részletekért lásd az explicit felület implementálását.
Interfész öröklése
A felületek egy vagy több más interfésztől örökölhetnek. A származtatott felületet megvalósító osztálynak a származtatott interfész és annak összes alapfelülete összes tagját implementálnia kell:
interface IDrawable
{
void Draw();
}
interface IShape : IDrawable
{
double Area { get; }
}
public class Circle(double radius) : IShape
{
public double Area => Math.PI * radius * radius;
public void Draw() =>
Console.WriteLine($"Drawing circle with area {Area:F2}");
}
A implementálandó IShape osztály implicit módon konvertálható IDrawable, mert IShape örökli azt.
Interfészek és absztrakt osztályok
Mind az interfészek, mind az absztrakt osztályok olyan szerződéseket határoznak meg, amelyeket a származtatott típusoknak teljesíteniük kell.
- Absztrakt osztály használata , ha a kapcsolódó típusok államot (mezőket), konstruktorokat vagy nem nyilvános tagokat osztanak meg. Az absztrakt osztályok lehetővé teszik a hierarchia továbbfejlesztét azáltal, hogy új tagokat ad hozzá alapértelmezett viselkedéssel a meglévő származtatott típusok feltörése nélkül.
- Akkor használjon interfészt , ha egy típusnak olyan szerződést kell teljesítenie, amely nem kapcsolódó hierarchiákon átvág, vagy ha több szerződést kell implementálnia. Az interfészek nem deklarálhatnak példánymezőket vagy konstruktorokat, így a legjobban az alaposztályt már tartalmazó típusok képességeinek hozzáadására alkalmasak. Speciális forgatókönyvek esetén az interfészek támogatják az alapértelmezett tag-implementációkat is.
Egy osztály csak egy alaposztálytól örökölhet, de több interfészt is implementálhat. Ez a megkülönböztetés gyakran jobb választássá teszi a felületeket a típushierarchiákon átvágó képességek meghatározásához.
Belső felületekkel való munka
Általában implementálhat egy belső felületet a nyilvános tagokkal, feltéve, hogy a felületi aláírás minden típusa nyilvánosan elérhető. Ha egy felület belső típusokat használ a tag-aláírásaiban, explicit implementációt kell használnia, mert a implementáló tag nem lehet nyilvános, miközben belső típusokat ad ki:
internal class InternalConfiguration
{
public string Setting { get; set; } = "";
}
internal interface ILoggable
{
void Log(string message);
}
internal interface IConfigurable
{
void Configure(InternalConfiguration config);
}
public class ServiceImplementation : ILoggable, IConfigurable
{
// Implicit implementation: ILoggable uses only public types in its signature
public void Log(string message) =>
Console.WriteLine($"Log: {message}");
// Explicit implementation: IConfigurable uses internal types
void IConfigurable.Configure(InternalConfiguration config) =>
Console.WriteLine($"Configured with: {config.Setting}");
}
Az előző példában IConfigurable egy belső típust InternalConfiguration használ a metódus-aláírásban.
ServiceImplementation explicit implementációt használ az adott taghoz. Ezzel szemben az aláírásában csak a nyilvános típusokat (string) használja, és implicit módon implementálható (ILoggable).
Alapértelmezett felülettagok és statikus absztrakt tagok
A felületek két speciális funkciót támogatnak, amelyek túlmutatnak az alapszintű szerződéseken:
- Az alapértelmezett illesztőtagok lehetővé teszik, hogy az interfész metódustörzset biztosítson. A implementálási típusok öröklik az alapértelmezett implementációt, és igény szerint felülbírálhatják azt. További információkért tekintse meg az alapértelmezett felületi metódusokat.
- A statikus absztrakt tagokhoz implementálási típusok szükségesek, hogy statikus tagot biztosítsanak, ami hasznos az operátori szerződések vagy a gyári minták definiálásához. További információ: statikus absztrakt tagok a felületeken.
A nyelvi referencia felületeiről szóló cikk mindkét funkciót ismerteti. A legtöbb mindennapi felülethasználat magában foglalja a jelen cikkben korábban ismertetett deklarálási és implementálási mintákat.
Interfészek összegzése
- Az interfész metódusok, tulajdonságok, események és indexelők szerződését határozza meg.
- Az interfészt megvalósító osztálynak vagy szerkezetnek implementációkat kell biztosítania az összes deklarált tag számára (kivéve, ha az interfész alapértelmezett implementációt biztosít).
- Nem lehet közvetlenül létrehozni egy felületet.
- 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.
- A felületnevek hagyományosan a .-val
Ikezdődnek.