C#中的接口

Vin*_*eet 8 c# oop interface

我是OOP的新手并且有一些问题.

  1. 为什么接口中声明的方法不能具有修饰符(public,private等).

  2. 在这段代码中:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

这两种方法都不需要修饰符,但是当我不使用接口时,X.add()如上所述,我需要公开实现.为什么?

jas*_*son 34

接口是合同.它说"我可以做这些事情." 有人向你递交了一个实例,IInterface其中你不能使用该合同中的某些方法,因为它们已被标记为不公开?

这是以这种方式设计语言的基本原理.对此的规范在语言规范的第13.2节中:

所有接口成员都隐式具有公共访问权限.接口成员声明包含任何修饰符是编译时错误.特别是,接口成员不能随修饰声明abstract,public,protected,internal,private, virtual,override,或static.

至于您的代码,这是显式接口实现的一个示例.当一个类或结构体实现两个接口,每个接口具有相同签名的成员时,它是最有用的.例如,既IEnumerableIEnumerable<T>定义一个方法GetEnumerator接受没有参数.

public interface IEnumerable {
    IEnumerator GetEnumerator();
}

public interface IEnumerable<T> : IEnumerable {
    IEnumerator<T> GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)

请注意,通过上述定义,任何实现的类也IEnumerable<T>必须实现IEnumerable.请记住,返回类型不是签名的一部分,因此我们与IEnumerable.GetEnumerator和冲突IEnumerable<T>.GetEnumerator.这是显式接口实现要解决的问题:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

显式接口实现的成员只能通过接口实例看到.从而:

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
Run Code Online (Sandbox Code Playgroud)

因此,在您的代码中

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
Run Code Online (Sandbox Code Playgroud)

这两种方法都不需要修饰符,但是当我不使用接口时,比如上面的X.add(),我需要公开实现.为什么?

好的,目前还不清楚你在这里问的确切内容.显式接口实现不允许访问修饰符.这是13.4:

这是一个显式接口成员实现,包括访问修饰符编译时错误,它是一个编译时错误,包括修饰语abstract,virtual,override,或static.

如果接口实现未标记为显式接口实现,则它必须具有访问修饰符public.这是13.4.4(接口映射):

类或结构的接口映射C定位了基类列表中指定的每个接口的每个成员的实现C.特定接口成员的实现I.M,其中IM声明成员的接口,通过检查每个类或结构来确定S,从C每个连续的基类开始并重复C,直到找到匹配为止

  • 如果S包含匹配的显式接口成员实现的声明IM,那么这个成员就是执行I.M

  • 否则,如果S包含一个匹配的非静态公共成员的声明M,那么这个成员就是执行I.M.

如果无法为基类列表中指定的所有接口的所有成员定位实现,则会发生编译时错误C.

因此,简而言之,编译器首先寻找显式接口实现.如果找不到,那么它会查找与正在实现的方法具有相同签名的非静态公共成员M.如果找不到一个发生编译时错误.所以规则是这样的.要实现接口成员I.M:

  1. 如果你I.M明确实现,那么语法是

    return-type I.M(parameter-list)

  2. 否则,语法是

    public return-type M(parameter-list)

因此,与

interface IAdd {
    int Add(int x, int y)
}
Run Code Online (Sandbox Code Playgroud)

我们可以明确地实施:

class Explicit : IAdd {
    int IAdd.Add(int x, int y) { return x + y; }
}
Run Code Online (Sandbox Code Playgroud)

或不:

class NotExplicit : IAdd {
    public int Add(int x, int y) { return x + y; }
}
Run Code Online (Sandbox Code Playgroud)

然后区别是Explicit.Add不可见的,除非Explicit输入的实例为IAdd:

IAdd explicitInterface = new Explicit();
explicitInterface.Add(2, 2);
Explicit explicit = new Explicit();
explicit.Add(2, 2); // compile-time error
Run Code Online (Sandbox Code Playgroud)

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

这有帮助吗?

  • 这个答案很疯狂. (6认同)

Geo*_*ton 1

因为接口成员自动是公共的。您通过接口定义契约,并且成员不公开是没有任何意义的,因为您必须在实现类中实现它们。