反对在接口上声明受保护访问成员的论点是什么?例如,这是无效的:
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; ... }
(不可否认,这不适用于struct
s)
我不能在界面中看到很多private
或者internal
修饰符,但是支持public
和protected
修饰符看起来非常合理.
我将通过将它们与s完全分开来尝试解释protected
成员的效用:interface
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
成员的类 - 这不是我们目前可以做的事情.
我想每个人都认为界面只有公共成员,没有实现细节.你在寻找的是一个抽象的课程.
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保护方法.那样就好.根据定义,接口是调用者和对象之间的契约,而不是类及其子类之间的契约.抽象类和我们这个概念一样接近.这没关系.你基本上提出的是语言中的另一个构造,通过它我们可以在不破坏构建的情况下将子类从一个基类切换到另一个基类.对我来说,这没有意义.
如果要创建类的子类,则子类是基类的特化.它应该完全了解基类的任何受保护成员.但是如果您突然想要将基类切换出来,那么子类应该与任何其他IOrange一起使用是没有意义的.
我想你有一个公平的问题,但这似乎是一个极端的案例,我认为没有任何好处.
看不出为什么会想要这个.如果希望派生类提供特定方法的实现,请转到抽象基类.接口就是 - 接口.公共合同,没有别的.将接口视为规范,它描述了实现对外部世界的看法.两针插头的规格没有说明(至少我认为)它的内部结构应该是什么样的.它必须与插头插座兼容.
(来源:made-in-china.com)
因为没有意义.界面是公开的合同.我是一名IThing,因此如果被问到我会执行IThing方法.您不能要求IThing确认它执行它无法告诉您的方法.
存在允许人们访问您的类而不知道具体实现是什么的接口.它完全将实现与数据传递合同分开.
因此,界面中的所有内容都必须是公共的.非公共成员仅在您有权访问实现时才有用,因此不会对接口定义做出有意义的贡献.
接口成员是公共API; 之类的东西protected
等都是实现细节-和接口不具有任何实现.我怀疑你要找的是显式接口实现:
public class NavelOrange : IOrange { public OrangePeel Peel { get { return new OrangePeel(); } } OrangePips IOrange.Seeds { get { return null; } } }