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

发布于 2024-07-13 01:25:06 字数 1784 浏览 11 评论 0原文

反对在接口上声明受保护访问成员的论点是什么? 例如,这是无效的:

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 不起作用)

我看不到 private的太多情况>internal 接口中的修饰符,但同时支持 publicprotected 修饰符似乎完全合理。


我将尝试通过将 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; } }
}

这不是特别有用,因为类已经暗示了这一点首先提供受保护的成员来签订合同。

但我们也可以这样做:

public interface IOrange : IOrangeSupport
{
   ...
}

从而将 IOrangeSupport 应用于所有实现 IOrange 的类,并要求它们提供特定的受保护成员 - 这不是我们目前可以做的事情。

What is the argument against declaring protected-access members on interfaces? This, for example, is invalid:

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

In this example, the interface IOrange would guarantee that implementors at least provide an OrangePips instance to their inheritors. If the implementor wanted to, they could expand the scope to full 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); } }
}

The intent of protected members on interfaces is to provide a support contract for inheritors (sub-classes), for example:

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

(Admittedly, this wouldn't work for structs)

I can't see much of a case for private or internal modifiers in interfaces, but supporting both public and protected modifiers seems perfectly reasonable.


I'm going to try explaining the utility of protected members on interfaces by separating them from interfaces entirely:

Let's imagine a new C# keyword, support, to enforce inheritor contracts, so that we declare things as follows:

public support IOrangeSupport
{
    OrangePips Seeds { get; }
}

This would allows us to contract classes to provide protected members to their inheritors:

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

This is not particularly useful, because classes would already imply this contract by providing the protected members in the first place.

But then we could also do this:

public interface IOrange : IOrangeSupport
{
   ...
}

Thereby applying IOrangeSupport to all classes which implement IOrange and requiring them to provide particular protected members - which is not something we can currently do.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

好倦 2024-07-20 01:25:06

我认为每个人都强调了只有公共成员而没有实现细节的接口这一点。 您正在寻找的是抽象类

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); } }
}

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

如果您要创建类的子类,则该子类是基类的特化。 它应该充分了解基类的任何受保护成员。 但是,如果您突然想要切换基类,则子类与任何其他 IOrange 一起使用是没有意义的。

我想你有一个合理的问题,但这似乎是一个极端的情况,说实话,我看不出它有任何好处。

I think everyone hammered the point of an interface having only public members, no implementation details. What you are looking for is an abstract class.

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); } }
}

Edit: It is fair to argue that if we have a PlasticOrange that derives from a class Ornament, it can only implement IOrange and not the Seeds protected method. That is fine. An interface by definition is a contract between a caller and an object, not between a class and its subclasses. The abstract class is as close as we come to this concept. And that is fine. What you are essentially proposing is another construct in the language through which we can switch subclasses from one base class to another without breaking the build. To me, this doesn't make sense.

If you are creating a subclass of a class, the subclass is a specialization of the base class. It should be fully aware of any protected members of the base class. But if you suddenly want to switch the base class out, it makes no sense that the subclass should work with any other IOrange.

I suppose you have a fair question, but it seems like a corner case and I don't see any benefit from it to be honest.

2024-07-20 01:25:06

不明白为什么有人想要这个。 如果您希望派生类提供特定方法的实现,请选择抽象基类。 接口就是接口。 一份公共合同,仅此而已。 将接口视为规范,它描述了外部世界如何看待实现。 两针插头的规范没有说明(至少我认为)其内部结构应该是什么样的。 它只需与插头插座接口兼容即可。
Plug
(来源:made-in-china.com)

Can't see why would one want this. If you want derived class to provide an implementation of a particular method, go for abstract base classes. Interfaces are just that - interfaces. A public contract, nothing else. Think of interface as of specification which describes how should the implementation look to the outside world. A specification for a two-pin plug does not state (at least I assume that) what it's internal structure should be like. It just must be interface-compatible with a plug socket.
Plug
(source: made-in-china.com)

梦情居士 2024-07-20 01:25:06

因为这没有意义。 接口是公开暴露的合约。 我是一个 IThing,因此如果有人要求我会执行 IThing 方法。 你不能要求 IThing 确认它执行它无法告诉你的方法。

Because it makes no sense. An interface is a publicly exposed contract. I am an IThing, therefore I will perform IThing methods if asked. You can't ask an IThing to confirm it performs methods it can't tell you about.

梦里人 2024-07-20 01:25:06

自 C# 8.0(2019 年 9 月)起,您可以在接口内拥有访问修饰符

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

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

请参阅这些帖子

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

仔细看看 C# 8 接口

Since C# 8.0 (September 2019) You can have an access modifier inside the interface

Check these changes in interface c# 8.0

Update interfaces with default interface methods in C# 8.0

See these posts

C# 8 Interfaces: Public, Private, and Protected Members

A Closer Look at C# 8 Interfaces

幼儿园老大 2024-07-20 01:25:06

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

因此,接口中的所有内容都必须是公共的。 非公共成员仅在您有权访问实现时才有用,因此不会对接口定义做出有意义的贡献。

Interfaces exist to allow people to access your class without knowing what the concrete implementation is. It completely divorices the implementation from the data passing contract.

Therefore, everything in an interface must be public. Non-public members are only useful if you have access to the implementation and therefore don't meaningfully contribute to an interface definition.

拥抱没勇气 2024-07-20 01:25:06

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

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

Interface members are a public API; things like protected etc are implementation details - and interfaces don't have any implementation. I suspect what you are looking for is explicit interface implementation:

public class NavelOrange : IOrange
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    OrangePips IOrange.Seeds { get { return null; } }
}
老旧海报 2024-07-20 01:25:06

界面就像钥匙的形状

这不是关键。

这不是锁。

这只是一个细长的接触点。

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

对于开锁的钥匙来说,重要的是它们具有相同的形状。

通过将形状(界面)公开,您可以让其他人创建兼容的锁或兼容的钥匙。

否则,将其(界面)设为内部,您将不允许其他人创建兼容的锁或兼容的钥匙。

An interface is just like the shape of a key.

enter image description here

It's not the key.

It's not the lock.

It's just the slim contact point.

For this reason all the members of the interface (that defines the shape of the key) must be public.

For a key to open a lock it is important that they both share the same shape.

By making the shape (the interface) public, you can let others create compatible locks or compatible keys.

Otherwise, making it (the interface) internal you will not allow others to create compatible locks or compatible keys.

空‖城人不在 2024-07-20 01:25:06

仅供记录:
从 C# 8.0 开始,接口现在可以包含受

  • 保护的成员
  • 私有成员
  • 实现

,这作为底线引入了一些以前仅在支持多重继承的语言中可用的功能,例如共享多个基本成员的实现。

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/default-interface-methods-versions" 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

Just for the record:
As of C# 8.0 interfaces now can contain

  • protected members
  • private members
  • implementation

Which as a bottom line introduces some features previously only available in languages that support multiple inheritance such as sharing implementation of multiple base members.

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

天邊彩虹 2024-07-20 01:25:06

接口是向客户端承诺某些功能的契约。 换句话说,接口的目的是能够将类型转换到其中并将其传递给需要该接口保证的功能的代码。 由于某种类型的客户端代码无法访问该类型的受保护成员,因此在接口中声明受保护的项是没有意义的。

An interface is a contract that promises certain functionality to clients. In other words, the purpose of an interface is to be able to cast a type into it and pass it around like that to code that needs the features guaranteed by that interface. Since client code of a type cannot access protected members of that type, it makes no sense to declare protected items in an interface.

满身野味 2024-07-20 01:25:06

与抽象基类相比,受保护的接口将允许(抽象类的)“多重继承”,我发现这很有用一两次......

in contrast to abstract base classes, protected interfaces would allow "multiple inheritance" (of abstract classes), which i would have found useful once or twice...

樱娆 2024-07-20 01:25:06

接口是关于某个对象可以做什么的,因此当使用实现该接口的类时,开发人员将期望所有成员都被实现,因此 protected 访问修饰符对接口没有任何意义。

An interface is all about what a certain object can do, so when using a class which implements that interface the developer will expect all the members to be implemented, so the protected access modifier won't mean anything for interfaces.

为你拒绝所有暧昧 2024-07-20 01:25:06

当前的接口设计有合理的判断,它为实现者提供了更大的灵活性。 请记住,接口通常是由框架程序员编写的,而实现者是不同的人。 强制实施将是不必要的严厉。

There's sound judgment in current design of interfaces which is that it offers implementers greater flexibility. Remember that very often interfaces are written by framework programmers and implementers are different folks. To enforce implementation would be needlessly harsh.

牵强ㄟ 2024-07-20 01:25:06

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

By implementing an interface the type states that it supports a specific set of methods. If any of these methods were not public, it would not be available to callers and thus the type would not support the interface as stated.

别再吹冷风 2024-07-20 01:25:06

接口仅包含公共成员。 受保护意味着您声明的任何内容仅适用于类和派生类实例。

An Interface contains only public members. Protected means whatever you're declaring is only available to the class and derived class instances.

关于从前 2024-07-20 01:25:06

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

顺便说一句,即使无法在接口中嵌套类,对接口成员应用内部访问修饰符仍然很有用,其效果是只有定义接口的程序集才能够为其定义任何实现。

Any class which implements a .net interface will have to include implementations of all of the interface members. Further, any class can expose to a derived class whatever members it wishes. Requiring that an implementation of an interface must include a member which will only be usable from derived classes would serve no useful purpose, unless either (1) such a member could be visible to something outside the interface, or (2) interface implementations could use members which they did not themselves define. If interfaces were allowed to include nested classes (which could access the interfaces' protected members), then protected interface members would make sense. Indeed, they could be very useful if a class nested within an interface could define extension methods for that interface. Unfortunately, no such facility exists.

BTW, even without being able to nest classes in interfaces, it would still be useful to apply an internal access modifier to interface members, with the effect that only the assembly where the interface is defined would be able to define any implementations for it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文