Udostępnij za pośrednictwem


interface (Odwołanie w C#)

Interfejs definiuje kontrakt. Każdy classelement lub struct record implementujący ten kontrakt musi zapewnić implementację elementów członkowskich zdefiniowanych w interfejsie. Interfejs może definiować domyślną implementację dla elementów członkowskich. Może również definiować static elementy członkowskie w celu zapewnienia jednej implementacji dla typowych funkcji. Począwszy od języka C# 11, interfejs może definiować static abstract elementy członkowskie lub static virtual zadeklarować, że typ implementujący musi podać zadeklarowane elementy członkowskie. Zazwyczaj metody deklarują, static virtual że implementacja musi definiować zestaw przeciążonych operatorów.

W poniższym przykładzie klasa ImplementationClass musi zaimplementować metodę o nazwie SampleMethod , która nie ma parametrów i zwraca wartość void.

Aby uzyskać więcej informacji i przykładów, zobacz Interfejsy.

Interfejs najwyższego poziomu, zadeklarowany w przestrzeni nazw, ale nie zagnieżdżony wewnątrz innego typu, można zadeklarować public lub internal. Wartość domyślna to internal. Zagnieżdżone deklaracje interfejsu, zadeklarowane wewnątrz innego typu, można zadeklarować przy użyciu dowolnego modyfikatora dostępu.

Elementy członkowskie interfejsu bez implementacji nie mogą zawierać modyfikatora dostępu. Członkowie z domyślną implementacją mogą zawierać dowolny modyfikator dostępu.

Przykładowy interfejs

interface ISampleInterface
{
    void SampleMethod();
}

class ImplementationClass : ISampleInterface
{
    // Explicit interface member implementation:
    void ISampleInterface.SampleMethod()
    {
        // Method implementation.
    }

    static void Main()
    {
        // Declare an interface instance.
        ISampleInterface obj = new ImplementationClass();

        // Call the member.
        obj.SampleMethod();
    }
}

Interfejs może być elementem członkowskim przestrzeni nazw lub klasy. Deklaracja interfejsu może zawierać deklaracje (podpisy bez żadnej implementacji) następujących elementów członkowskich:

Domyślne elementy członkowskie interfejsu

Powyższe deklaracje składowe zwykle nie zawierają treści. Element członkowski interfejsu może zadeklarować treść. Elementy członkowskie w interfejsie są domyślną implementacją. Elementy członkowskie z ciałami umożliwiają interfejsowi zapewnienie implementacji "domyślnej" dla klas i struktur, które nie zapewniają zastępowania implementacji.

Ważne

Dodanie domyślnych elementów członkowskich wymusza każdą ref struct implementację interfejsu w celu dodania jawnej deklaracji tego elementu członkowskiego.

Interfejs może obejmować:

Statyczne abstrakcyjne i wirtualne elementy członkowskie

Począwszy od języka C# 11, interfejs może deklarować static abstract i static virtual składowe dla wszystkich typów składowych z wyjątkiem pól. Interfejsy mogą zadeklarować, że typy implementujące muszą definiować operatory lub inne statyczne elementy członkowskie. Ta funkcja umożliwia ogólne algorytmy określania zachowania przypominającego liczbę. Przykłady można zobaczyć w typach liczbowych w środowisku uruchomieniowym platformy .NET, takich jak System.Numerics.INumber<TSelf>. Te interfejsy definiują typowe operatory matematyczne implementowane przez wiele typów liczbowych. Kompilator musi rozpoznawać wywołania metod static virtual i w static abstract czasie kompilacji. Metody static virtual i static abstract zadeklarowane w interfejsach nie mają mechanizmu wysyłania środowiska uruchomieniowego analogicznego do virtual lub abstract metod zadeklarowanych w klasach. Zamiast tego kompilator używa informacji o typie dostępnych w czasie kompilacji. W związku z static virtual tym metody są prawie wyłącznie deklarowane w interfejsach ogólnych. Ponadto większość interfejsów, które deklarują metody lub deklarująstatic virtual, że jeden z parametrów typu musi implementować zadeklarowany interfejs.static abstract Na przykład interfejs deklaruje, INumber<T> że T musi implementować INumber<T>element . Kompilator używa argumentu typu do rozpoznawania wywołań metod i operatorów zadeklarowanych w deklaracji interfejsu. Na przykład int typ implementuje INumber<int>wartość . Gdy parametr T typu oznacza argument inttypu , static wywoływane są elementy członkowskie zadeklarowane int na. Alternatywnie, gdy double jest argumentem typu, static elementy członkowskie zadeklarowane w typie double są wywoływane.

Ważne

Wysyłanie metody dla static abstract metod zadeklarowanych w interfejsach i static virtual jest rozpoznawane przy użyciu typu czasu kompilacji wyrażenia. Jeśli typ środowiska uruchomieniowego wyrażenia pochodzi z innego typu czasu kompilacji, wywoływane będą metody statyczne w typie podstawowym (czas kompilacji).

Tę funkcję można wypróbować, pracując z samouczkiem dotyczącym statycznych abstrakcyjnych elementów członkowskich w interfejsach.

Dziedziczenie interfejsu

Interfejsy mogą nie zawierać stanu wystąpienia. Pola statyczne są teraz dozwolone, ale pola wystąpień nie są dozwolone w interfejsach. Właściwości automatyczne wystąpienia nie są obsługiwane w interfejsach, ponieważ niejawnie deklarują ukryte pole. Ta reguła ma subtelny wpływ na deklaracje właściwości. W deklaracji interfejsu poniższy kod nie deklaruje automatycznie zaimplementowanej właściwości, tak jak w obiekcie class lub struct. Zamiast tego deklaruje właściwość, która nie ma implementacji domyślnej, ale musi być zaimplementowana w dowolnym typie, który implementuje interfejs:

public interface INamed
{
  public string Name {get; set;}
}

Interfejs może dziedziczyć z co najmniej jednego interfejsu podstawowego. Gdy interfejs dziedziczy z innego interfejsu, typ implementowania interfejsu pochodnego musi implementować wszystkie elementy członkowskie w interfejsach podstawowych, a także te zadeklarowane w interfejsie pochodnym, jak pokazano w poniższym kodzie:

public interface I1
{
    void M1();
}

public interface I2 : I1
{
    void M2();
}

public class C : I2
{
    // implements I1.M1
    public void M1() { }
    // implements I2.M2
    public void M2() { }
}

Gdy interfejs zastępuje metodę zaimplementowaną w interfejsie podstawowym, musi używać jawnej składni implementacji interfejsu.

Gdy lista typów podstawowych zawiera klasę bazową i interfejsy, klasa bazowa musi znajdować się na liście jako pierwsza.

Klasa, która implementuje interfejs, może jawnie implementować elementy członkowskie tego interfejsu. Jawnie zaimplementowany element członkowski nie może być dostępny za pośrednictwem wystąpienia klasy, ale tylko za pośrednictwem wystąpienia interfejsu. Ponadto dostęp do domyślnych elementów członkowskich interfejsu można uzyskać tylko za pośrednictwem wystąpienia interfejsu.

Aby uzyskać więcej informacji na temat jawnej implementacji interfejsu, zobacz Jawna implementacja interfejsu.

Przykładowa implementacja interfejsu

W poniższym przykładzie pokazano implementację interfejsu. W tym przykładzie interfejs zawiera deklarację właściwości, a klasa zawiera implementację. Każde wystąpienie klasy, która implementuje, ma właściwości x liczb całkowitych IPoint i y.

interface IPoint
{
    // Property signatures:
    int X { get; set; }

    int Y { get; set; }

    double Distance { get; }
}

class Point : IPoint
{
    // Constructor:
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }

    // Property implementation:
    public int X { get; set; }

    public int Y { get; set; }

    // Property implementation
    public double Distance =>
       Math.Sqrt(X * X + Y * Y);
}

class MainClass
{
    static void PrintPoint(IPoint p)
    {
        Console.WriteLine("x={0}, y={1}", p.X, p.Y);
    }

    static void Main()
    {
        IPoint p = new Point(2, 3);
        Console.Write("My Point: ");
        PrintPoint(p);
    }
}
// Output: My Point: x=2, y=3

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz sekcję Interfejsy specyfikacji języka C#, specyfikację funkcji dla C# 8 — domyślnych elementów członkowskich interfejsu oraz specyfikację funkcji dla języka C# 11 — statycznych elementów abstrakcyjnych w interfejsach

Zobacz też