2010-01-29 9 views
8

Ich bin neu in OOP und habe ein paar Fragen.Schnittstelle in C#

  1. Warum können in einer Schnittstelle deklarierte Methoden keine Modifikatoren (public, private usw.) haben.

  2. In diesem Code:

class Program 
{ 
    static void Main(string[] args) 
    { 
     X ob = new Y(); 
     ob.add(4, 5); 
     Z ob1 = new Y(); 
     ob1.mull(2, 3); 
     Console.Read(); 
    } 
} 

public interface X 
{ 
    void add(int x, int y); 
} 
public interface Z 
{ 
    void mull(int x, int y); 
} 

class Y : X, Z 
{ 
    void X.add(int x, int y)//here we are not decalring it as public ,why? 
    { 
     Console.WriteLine("sum of X and y is " + (x + y)); 
    } 
    void Z.mull(int x, int y) 
    { 
     Console.WriteLine("product of X and Y is" + (x * y)); 
    } 
} 

Beide Methoden erfordern keine Modifikatoren, aber wenn ich nicht Schnittstelle verwenden, wie X.add() oben, ich brauche die Umsetzung öffentlich zu machen. Warum?

+0

möglich Duplikat von http://Stackoverflow.com/questions/1652123/is-there-a-reason-you-cann-not-define-the-access-modifier-on-a-method-or-in-in- an-int –

Antwort

1

Da Schnittstellenmitglieder automatisch öffentlich sind. Sie definieren einen Vertrag über eine Schnittstelle und es wäre für die Mitglieder nicht sinnvoll, nicht öffentlich zu sein, da Sie sie in Ihrer Implementierungsklasse implementieren müssen.

34

Eine Schnittstelle ist ein Vertrag. Es sagt: "Ich kann diese Dinge tun." Was ist der Sinn von jemandem, der Ihnen eine Instanz von IInterface übergibt, in der Sie einige der Methoden in diesem Vertrag nicht verwenden können, weil sie als nicht öffentlich markiert wurden?

Dies ist der Grund für die Gestaltung der Sprache auf diese Weise. Die Spezifikation hierfür ist in §13.2 der Sprachspezifikation:

Alle Schnittstellenmitglieder haben implizit öffentlichen Zugriff. Es ist ein Kompilierungsfehler für Interface-Member-Deklarationen, die alle Modifikatoren enthalten. Insbesondere können Schnittstellen Mitglieder nicht mit den Modifikatoren abstract, public, protected, internal, private,virtual, override oder static deklariert werden.

Wie für Ihren Code, das ist ein Beispiel für explicit interface implementation. Es ist am nützlichsten, wenn eine Klasse oder Struktur zwei Schnittstellen mit jeweils einem Element mit der gleichen Signatur implementiert. Zum Beispiel definieren sowohl IEnumerable als auch IEnumerable<T> eine Methode GetEnumerator, die keine Parameter akzeptiert.

public interface IEnumerable { 
    IEnumerator GetEnumerator(); 
} 

public interface IEnumerable<T> : IEnumerable { 
    IEnumerator<T> GetEnumerator(); 
} 

Beachten Sie, dass durch die oben genannten Definitionen, die jede Klasse IEnumerable<T> implementiert auch IEnumerable implementieren müssen. Beachten Sie, dass der Rückgabetyp nicht Teil der Signatur ist und somit ein Konflikt mit IEnumerable.GetEnumerator und IEnumerable<T>.GetEnumerator vorliegt. Dies ist, was explizite Schnittstellenimplementierung ist zu lösen gemeint:

class X<T> : IEnumerable<T> { 
    List<T> _list = new List<T>(); 
    public IEnumerator<T> GetEnumerator() { 
     return _list.GetEnumerator(); 
    } 

    IEnumerator GetEnumerator() { 
     return GetEnumerator(); // invokes IEnumerable<T>.GetEnumerator 
    } 
} 

Mitglieder, die expliziten Interface-Implementierungen sind nur sichtbar durch eine Instanz der Schnittstelle. Also:

X<int> x = new X<int>(); 
var e1 = x.GetEnumerator(); // invokes IEnumerable<int>.GetEnumerator 
          // IEnumerable.GetEnumerator is not visible 
IEnumerable y = x; 
var e2 = y.GetEnumerator(); // invokes IEnumerable.GetEnumerator 

So in Ihrem Code

X ob = new Y(); 
ob.add(1, 2); // X.add is visible through interface 
Y y = new Y(); 
y.add(1, 2); // compile-time error, X.add is not visible 

Beide Methoden erfordern keine Modifikatoren, aber wenn ich nicht Schnittstelle verwenden, wie X.add() oben, muss ich Machen Sie die Implementierung öffentlich. Warum?

Okay, es ist nicht klar, was genau Sie hier fragen. Zugriffsmodifizierer sind für explizite Schnittstellenimplementierungen nicht zulässig. Das ist 13,4:

Es ist ein Fehler bei der Kompilierung für eine explizite Schnittstellenmemberimplementierung Zugriffsmodifikatoren aufzunehmen, und es ist ein Fehler Compile-Zeit die Modifikatoren abstract, virtual, override, einschließen oder static.

Wenn eine Interface-Implementierung nicht als eine explizite Schnittstellenimplementierung gekennzeichnet ist, dann muss es den Zugriffsmodifikator haben public. Dies ist 13.4.4 (Interface mapping):

Interface-Mapping für eine Klasse oder struct C für jedes Mitglied jeder Schnittstelle eine Implementierung findet in der Basisklasse Liste von C angegeben. Die Umsetzung eines bestimmten Schnittstellenelement I.M, wo I ist die Schnittstelle in der das Element M deklariert ist, wird durch Prüfen jede Klasse oder struct S, beginnend für jede aufeinanderfolgende Basisklasse von C mit C und Wiederholen bestimmt, bis eine Übereinstimmung befindet

  • Wenn S enthält eine Erklärung einer expliziten Interface-Member-Implementierung, die I und M übereinstimmt, dann ist dieses Mitglied die Umsetzung von I.M

  • Andernfalls, wenn S eine Deklaration eines nicht statischen öffentlichen Mitglieds enthält, das mit M übereinstimmt, ist dieses Element die Implementierung von I.M.

Ein Fehler bei der Kompilierung tritt auf, wenn Implementierungen kann nicht für alle Mitglieder aller Schnittstellen in der Basisklasse Liste der C angegeben befindet.

Kurz gesagt, der Compiler sucht zuerst nach einer expliziten Schnittstellenimplementierung. Wenn es keinen finden kann, sucht es nach einem nicht statischen, öffentlichen Mitglied mit der gleichen Signatur wie die Methode M, die implementiert wird. Wenn es keinen finden kann, tritt ein Kompilierungsfehler auf. Also sind die Regeln das.Um eine Schnittstelle zu implementieren Mitglied I.M:

  1. Wenn Sie I.M implementieren explizit dann die Syntax

    return-type I.M(parameter-list)

  2. Ansonsten ist die Syntax

    public return-type M(parameter-list)

So mit

Wir implementieren ausdrücklich:

class Explicit : IAdd { 
    int IAdd.Add(int x, int y) { return x + y; } 
} 

oder nicht:

class NotExplicit : IAdd { 
    public int Add(int x, int y) { return x + y; } 
} 

Der Unterschied ist dann, dass Explicit.Add nicht sichtbar ist, wenn Instanzen von Explicit als IAdd eingegeben werden :

IAdd explicitInterface = new Explicit(); 
explicitInterface.Add(2, 2); 
Explicit explicit = new Explicit(); 
explicit.Add(2, 2); // compile-time error 

während

IAdd notExplicitInterface = new NotExplicit(); 
notExplicitInterface.Add(2, 2); 
NotExplicit notExplicit = new NotExplicit(); 
notExplicit.Add(2, 2); // okay, NOT a compile-time error as above 

Does diese Hilfe?

+6

Diese Antwort ist verrückt gründlich. –

+0

In Ihrer kurzen Antwort muss etwas fehlen. Ich bin immer noch auf der Suche nach ... –

1

Gerade von Microsoft: „Interface Mitglieder sind immer öffentlich, da der Zweck einer Schnittstelle ist, andere Arten, den Zugang zu ermöglichen, eine Klasse oder Struktur. "

+0

Vielleicht möchten Sie Ihre Links reparieren. –

+0

Dies wurde behoben, thx. – alchemical

0

Da Funktionen, Felder usw., die in Interface deklariert sind, standardmäßig immer den öffentlichen Modifikator haben. Also, wenn Sie es implementieren, müssen Sie nicht öffentlich eingeben, weil Klasse bereits jetzt Methode ist Interface-Implementierung so seine Öffentlichkeit. In Klassen sind alle Felder und Methoden privet, aber taub.

1

Da Ihre beiden Schnittstellen keine Methoden mit derselben Signatur definieren, benötigen Sie keine explizite Implementierung. Sie könnten wie folgt vorgehen:

public void add(int x, int y) 
{ 
    Console.WriteLine("sum of X and y is " + (x + y)); 
} 
public void mull(int x, int y) 
{ 
    Console.WriteLine("product of X and Y is" + (x * y)); 
} 

Die implizite Implementierung einer Schnittstelle ist, und jetzt ist es einfacher, diese Methoden auf einer Instanz der Klasse zu nennen. Rufen Sie einfach myInstance.add(1, 2) an, anstatt myInstance als Instanz der Schnittstelle X zu übertragen.

0

Dies ist der Unterschied zwischen einer Explict und Implict Implementierung einer Schnittstelle.

Normalerweise möchten Sie eine Schnittstelle implizit implementieren, was bedeutet, dass die implementierten Elemente öffentlich verfügbar sind. Dies ist sinnvoll, wenn Sie bedenken, dass die Implementierung einer Schnittstelle normalerweise bedeutet, dass eine Klasse ein bestimmtes Feature ausführen kann (z. B. über IDisposable entsorgt werden kann).

In Szenarien, in denen Sie einen Typ benötigen, um eine Schnittstelle zu implementieren, aber nicht möchten, dass diese Schnittstellenmitglieder öffentlich zugänglich sind, verwenden Sie eine explizite Implementierung. Die Mitglieder sind immer noch erreichbar, aber nur wenn der Typ über die Schnittstelle referenziert wird.

1

Ich werde die von Ihnen gemeldeten Symptome unterstützen und erklären, anstatt zu erklären, warum der öffentliche Modifikator unnötig ist. die anderen Antworten haben das angemessen erklärt.

Wahrscheinlich ist der Grund, warum Sie verwirrt sind, dass Sie explizite Schnittstellenimplementierung verwenden. Wenn Sie eine explizite Schnittstellenimplementierung verwenden, müssen Sie die Objektinstanz auf diesen Schnittstellentyp umwandeln, bevor Sie ihre Methoden aufrufen können.

Wenn Sie das "X" entfernen. Von Ihrer X.Add-Implementierung können Sie die Schnittstelle ohne explizite Umwandlung "sehen" und verwenden. Dies ist eine "implizite" Schnittstellenimplementierung. Solange Sie keine Namenskollisionen oder einen Grund haben, die Schnittstellenmitglieder für normale Clients etwas weniger sichtbar zu machen, möchten Sie wahrscheinlich eine implizite Schnittstellenimplementierung bevorzugen.

Verwandte Themen