C# 为什么可以';我是否有受保护的接口成员?
反对在接口上声明受保护的访问成员的理由是什么?例如,这是无效的:C# 为什么可以';我是否有受保护的接口成员?,c#,interface,protected,access-modifiers,C#,Interface,Protected,Access Modifiers,反对在接口上声明受保护的访问成员的理由是什么?例如,这是无效的: public interface IOrange { public OrangePeel Peel { get; } protected OrangePips Seeds { get; } } 在本例中,接口IOrange将保证实现者至少向其继承者提供OrangePips实例。如果实现者愿意,他们可以将范围扩展到完整的public: public class NavelOrange : IOrange {
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); } }
}
接口上受保护的成员的意图是为继承者(子类)提供支持契约,例如:
public class SpecialNavelOrange : NavelOrange
{
...
// Having a seed value is useful to me.
OrangePips seeds = this.Seeds;
...
}
(无可否认,这不适用于struct
s)
我看不出有什么理由在接口中使用private
或internal
修饰符,但同时支持public
和protected
修饰符似乎是完全合理的
我将尝试通过将
受保护的成员与接口
完全分离,来解释受保护的成员在接口
上的效用:
让我们设想一个新的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; } }
}
这并不是特别有用,因为类通过首先提供受保护的
成员已经暗示了这种契约
但我们也可以这样做:
public interface IOrange : IOrangeSupport
{
...
}
因此,将IOrangeSupport
应用于实现IOrange
的所有类,并要求它们提供特定的受保护的
成员—这是我们目前无法做到的。接口就是关于某个对象可以做什么,因此,当使用实现该接口的类时,开发人员希望实现所有成员,因此受保护的访问修饰符对接口没有任何意义;像protected
等都是实现细节,而接口没有任何实现。我怀疑您需要的是显式接口实现:
public class NavelOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
OrangePips IOrange.Seeds { get { return null; } }
}
接口仅包含公共成员。受保护意味着您所声明的内容仅对类和派生类实例可用。接口允许人们在不知道具体实现是什么的情况下访问您的类。它将实现与数据传递契约完全分离
因此,接口中的所有内容都必须是公共的。非公共成员只有在您有权访问实现并且因此对接口定义没有意义的贡献时才有用。,因为它没有意义。接口是公开的契约。我是一个IThing,因此如果有人要求,我将执行IThing方法。你不能要求一个IThing确认它执行了它不能告诉你的方法。看不出为什么要这样做。如果希望派生类提供特定方法的实现,请使用抽象基类。接口就是这样的接口。公共合同,没有别的。将接口视为描述实现应如何面向外部世界的规范。双针插头的规格并没有说明(至少我认为)它的内部结构应该是什么样的。它必须是接口兼容的插头插座。
(来源:)在当前的接口设计中有一个合理的判断,即它为实现者提供了更大的灵活性。记住,接口通常是由框架程序员编写的,而实现者是不同的人。强制实施将是不必要的苛刻。接口是向客户承诺某些功能的契约。换句话说,接口的目的是能够将类型强制转换到接口中,并像这样将其传递给需要该接口保证的特性的代码。由于类型的客户端代码无法访问该类型的受保护成员,因此在接口中声明受保护项是没有意义的。通过实现接口,该类型声明它支持一组特定的方法。如果这些方法中的任何一个不是公共的,则调用者将无法使用它,因此该类型将不支持所述的接口 我认为每个人都强调了界面只有公共成员,没有实现细节的观点。你要找的是一份工作
编辑:公平地说,如果我们有一个从类装饰派生的PlasticOrange,它只能实现IOrange,而不能实现种子保护方法。那很好。接口的定义是调用方和对象之间的契约,而不是类及其子类之间的契约。抽象类与这个概念非常接近。那很好。本质上,您所建议的是语言中的另一个构造,通过它,我们可以在不破坏构建的情况下将子类从一个基类切换到另一个基类。对我来说,这毫无意义
如果您正在创建一个类的子类,则该子类是基类的专门化。它应该完全了解基类的任何受保护成员。但是,如果您突然想要切换基类,那么子类应该与任何其他IOrange一起工作是毫无意义的
我想你有一个公平的问题,但这似乎是一个小问题,老实说,我看不出它有什么好处。任何实现.net接口的类都必须包含所有接口成员的实现。此外,任何类都可以向派生类公开它想要的任何成员。要求一个接口的实现必须包含一个只能从派生类中使用的成员是没有用的,除非(1)这样的成员可以对接口之外的东西可见,或者(2)接口实现可以使用它们没有使用的成员
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); } }
}