为什么我不能有受保护的接口成员?

反对在接口上声明 protected-access 成员的理由是什么? 例如,这是无效的:

public interface IOrange
{
public OrangePeel Peel { get; }
protected OrangePips Seeds { get; }
}

在本例中,接口 IOrange将保证实现者 至少向其继承者提供一个 OrangePips实例。如果实施者愿意,他们可以将范围扩大到完整的 public:

public class NavelOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
protected OrangePips Seeds { get { return null; } }
}


public class ValenciaOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
public OrangePips Seeds { get { return new OrangePips(6); } }
}

protected成员在接口上的意图是为 继承人(子类)提供一个支持契约,例如:

public class SpecialNavelOrange : NavelOrange
{
...
// Having a seed value is useful to me.
OrangePips seeds = this.Seeds;
...
}

(不可否认,这对 structs 不起作用)

我看不出在接口中有多少 privateinternal修饰符的情况,但是同时支持 publicprotected修饰符似乎是完全合理的。


我将尝试通过将 protected成员与 interface成员完全分开来解释 protected成员在 interface上的作用:

让我们设想一个新的 C # 关键字 support来强制执行继承者契约,这样我们就可以像下面这样声明:

public support IOrangeSupport
{
OrangePips Seeds { get; }
}

这将允许我们对类进行契约,以便为其继承者提供受保护的成员:

public class NavelOrange : IOrange, IOrangeSupport
{
public OrangePeel Peel { get { return new OrangePeel(); } }
protected OrangePips Seeds { get { return null; } }
}

这并不特别有用,因为类首先通过提供 protected成员已经暗示了这个约定。

但是我们也可以这样做:

public interface IOrange : IOrangeSupport
{
...
}

因此,将 IOrangeSupport应用到所有实现 IOrange的类,并要求它们提供特定的 protected成员——这是我们目前无法做到的。

66517 次浏览

接口是关于特定对象可以做什么的,所以当使用实现该接口的类时,开发人员会期望所有成员都被实现,所以受保护的访问修饰符对接口没有任何意义。

接口成员 是一个公共 API; 像 protected这样的东西都是实现细节-而接口没有 任何实现。我怀疑您正在寻找的是显式的接口实现:

public class NavelOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
OrangePips IOrange.Seeds { get { return null; } }
}

接口只包含公共成员。受保护意味着无论您声明什么,都只对类和派生类实例可用。

接口的存在是为了允许人们在不知道具体实现是什么的情况下访问您的类。它完全脱离了数据传递契约的实现。

因此,接口中的所有内容都必须是公共的。非公共成员只有在您可以访问实现并且因此无法对接口定义做出有意义的贡献的情况下才有用。

因为这毫无意义。接口是公开公开的契约。我是一个 IThing,因此如果需要,我将执行 IThing 方法。你不能要求一个 IThing 确认它执行的方法它不能告诉你。

不明白为什么会有人想要这个。如果希望派生类提供特定方法的实现,可以使用抽象基类。接口就是接口。公共合同,没别的了。把接口看作描述实现应该如何看待外部世界的规范。一个双引脚插头的规范并没有说明(至少我是这样假设的)它的内部结构应该是什么样的。它只是必须与插头插座接口兼容。 Plug
(来源: Made-in-china.com)

在当前的接口设计中有一个合理的判断,那就是它为实现者提供了更大的灵活性。请记住,接口通常是由框架程序员编写的,而实现者是不同的人。强制执行将是不必要的苛刻。

接口是承诺向客户端提供某些功能的契约。换句话说,接口的目的是能够将类型强制转换为接口,并像这样将其传递给需要该接口所保证的特性的代码。由于类型的客户端代码不能访问该类型的受保护成员,因此在接口中声明受保护项是没有意义的。

通过实现接口,该类型声明它支持一组特定的方法。如果这些方法中的任何一个不是公共的,那么调用方将无法使用它,因此类型将不支持所述的接口。

我认为每个人都强调了接口只有公共成员,没有实现细节的观点。你要找的是 抽象类

public interface IOrange
{
OrangePeel Peel { get; }
}


public abstract class OrangeBase : IOrange
{
protected OrangeBase() {}
protected abstract OrangePips Seeds { get; }
public abstract OrangePeel Peel { get; }
}


public class NavelOrange : OrangeBase
{
public override OrangePeel Peel { get { return new OrangePeel(); } }
protected override OrangePips Seeds { get { return null; } }
}


public class ValenciaOrange : OrangeBase
{
public override OrangePeel Peel { get { return new OrangePeel(); } }
protected override OrangePips Seeds { get { return new OrangePips(6); } }
}

编辑: 可以公平地说,如果我们有一个从类装饰派生出来的 PlasticOrange,它只能实现 IOrange,而不能实现 Seeds protected 方法。没关系。根据定义,接口是调用方和对象之间的契约,而不是类及其子类之间的契约。抽象类是我们最接近这个概念的类。没关系。本质上,您所提议的是语言中的另一个构造,通过它我们可以将子类从一个基类切换到另一个基类,而不会破坏构建。对我来说,这说不通。

如果要创建类的子类,则该子类是基类的专门化。它应该完全知道基类的任何受保护成员。但是如果您突然想要切换基类,那么子类应该与任何其他 IOrange 一起工作是没有意义的。

我想你有一个合理的问题,但它似乎是一个角落的情况下,我没有看到任何好处,从它老实说。

实现。Net 接口必须包括所有接口成员的实现。此外,任何类都可以向派生类公开它希望的任何成员。要求一个接口的实现必须包含一个只能从派生类中使用的成员是没有用的,除非(1)这样一个成员可以对接口之外的东西可见,或者(2)接口实现可以使用它们自己没有定义的成员。如果允许接口包含嵌套类(可以访问接口的 protected成员) ,那么 protected接口成员就有意义了。实际上,如果嵌套在接口中的类可以为该接口定义扩展方法,那么它们可能非常有用。不幸的是,没有这样的设施存在。

顺便说一句,即使不能在接口中嵌套类,对接口成员应用 internal访问修饰符仍然是有用的,因为只有定义了接口的程序集才能为其定义任何实现。

接口就像键的 形状

enter image description here

不是钥匙。

不是锁的问题。

只是接触点太小了。

因此,接口的所有成员(定义键形状的成员)必须是公共的。

对于打开一把锁的钥匙来说,两把钥匙形状相同是很重要的。

通过制作形状(接口) 公众人士,您可以让其他人创建兼容的锁或兼容的钥匙。

否则,使它(接口) 内部您将不允许其他人创建兼容锁或兼容密钥。

与抽象基类不同,受保护的接口允许“多重继承”(抽象类) ,我曾经发现这一点很有用... ..。

从 C # 8.0(2019年9月)开始,你可以在接口内部使用一个访问修饰符

检查接口 c # 8.0中的这些更改

使用 C # 8.0中的默认接口方法更新接口

看看这些帖子

C # 8接口: 公共、私有和受保护的成员

C # 8接口的进一步研究

郑重声明: 从 C # 8.0开始,接口现在可以包含

  • 受保护的成员
  • 私人会员
  • 实施

作为底线,它引入了一些以前只能在支持多重继承的语言中使用的特性,比如共享多个基本成员的实现。

Https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/default-interface-methods-versions Https://jeremybytes.blogspot.com/2019/11/c-8-interfaces-public-private-and.html