C# 多接口继承不允许具有相同名称的公共访问修饰符

Posted

技术标签:

【中文标题】C# 多接口继承不允许具有相同名称的公共访问修饰符【英文标题】:C# Multiple Interface Inheritance does not allow public access modifier with same name 【发布时间】:2015-10-03 09:41:21 【问题描述】:

所以这让我很困惑。 假设有两个接口。

public interface a

    void foo();


public interface b

    void foo();

这两个接口都有一个函数 foo,我有一个提供显式实现的类:

public class alpha : a, b

    // why can't I put an access modifier here?
    // How would you be able to hide this from a derived class
    void a.foo()
    
        Console.WriteLine("a");
    

   void b.foo()
    
        Console.WriteLine("b");
    

还有一个从 alpha 派生的类

public class beta : alpha


你如何将 foo 设为私有或受保护,因为 alpha 不允许在显式实施时使用访问修饰符,什么可以阻止某人调用:

var be = new beta();
(be as b).foo();

编辑

如果我不明确提供实现,我怎么可以提供访问修饰符?

public class alpha : a, b

   //why this compile? 
   public void foo()
    
        Console.WriteLine("both");
    


【问题讨论】:

你不能。这就是显式接口实现的工作方式。将对象转换为该特定的显式接口将公开成员。如果你不希望它被暴露,不要保证它在你的界面中。 没有办法隐藏实现,但是...您也可以在b 上显式实现foo beta,抛出异常... 也许这是XY problem - 请告诉我们您为什么要在beta 上隐藏foo... 请注意,在“显式提供实现我可以提供访问修饰符”-“可以”部分不完全正确-因为接口实现必须是public或显式 隐式实现的唯一选择是“必须指定public”而不是“可以提供修饰符”。 【参考方案1】:

由于接口a 是公共的,任何实现a 的类都必须使a 的方法可以公开访问,无论是隐式(通过公共方法)还是显式。显式实现是“某种”私有的,因为它们只能通过接口访问。

简而言之,没有办法完全“隐藏”foo - 你的类同时实现了ab,所以这些方法必须我做可以通过某种方式访问​​。

即使您只有 一个 接口也是如此 - 具有多个方法名称冲突的接口只会迫使您明确实现。如果你有一个接口,foo 要么必须是 public 要么是显式的。

【讨论】:

为什么我不明确提供实现我可以提供访问修饰符? 您可以提供访问修饰符,但必须是public。如果接口是public,则隐式实现必须是public。除了public,您不能将foo 设为任何其他内容,否则您违反了接口约定。 哦,奇怪的是你不能在显式实现时提供公共但你只能在隐式实现时提供公共 @johnny5 语言规则有时会导致这种奇怪的问题。请注意,这种特殊情况的实现可以来自子类的基类和接口 - 所以如果父类想要公开方法,它将使其成为私有/受保护的,因此需要防止派生类当派生类上的接口强制它公开时,避免公开此类方法。 @johnny5 这是你的情况,是的,因为 interface 是公开的。如果接口是internal,则方法可以是internalpublic。实现不能比接口更难访问【参考方案2】:

什么可以阻止某人打电话

没什么,这才是重点!

betab,因此您可以将其视为 b。如果您选择将其转换为 b 并调用显式的 foo 实现,您将获得 b 实现。

【讨论】:

为什么我不明确提供实现我可以提供访问修饰符? 选择 1 - public.【参考方案3】:

如其他答案所示,这些是语言规则,必须遵守。

说明为什么需要在接口实现上明确指定public 的示例:

class Base

   protected void Foo()   


public interface IFoo

   void Foo();

Base 明确选择不向类的用户公开方法Foo(派生的除外,也可以是private)。

现在,如果另一个类想要从Base 派生并同时实现IFoo。如果语言允许只选择实现而不考虑访问修饰符,这意味着Base.Foo 现在通过派生方式暴露给每个调用者:

class Derived : Base, IFoo 

    // hypothetical compiler allows to pick any matching `void Foo` 
    // including inherited `protected void Base.Foo()`

这显然违背了 Base 类隐藏 Foo 方法的意图 - 所以语言必须要求 Foopublic 才能被视为接口的一部分。

因此,您最终会在接口实现上使用“可选”访问修饰符,而您只有一个选项 - 必须指定 public

注意Derived 有几个选项来处理Foo - 显式实现和new 的影子:

class Derived : Base, IFoo

   new public void Foo() 

【讨论】:

以上是关于C# 多接口继承不允许具有相同名称的公共访问修饰符的主要内容,如果未能解决你的问题,请参考以下文章

C# 五大修饰符

在 C# 中,我们可以对接口使用受保护的访问修饰符吗?

C#语言中的修饰符汇总

C#中的默认访问修饰符

c# 曾经面试题

2017-4-14访问修饰符 封装 继承 多态