C# 有私有继承和受保护继承的概念吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 09:13:22  来源:igfitidea点击:

Does C# have the notion of private and protected inheritance?

提问by mmattax

Does C# have the notion of private / protected inheritance, and if not, why?

C# 是否有私有/受保护继承的概念,如果没有,为什么?

C++

C++


class Foo : private Bar {
 public:
   ...
 }; 

C#

C#


public abstract NServlet class : private System.Web.UI.Page
{
    // error "type expected"
}

I am implementing a "servlet like" concept in an .aspx page and I don't want the concrete class to have the ability to see the internals of the System.Web.UI.Page base.

我在 .aspx 页面中实现了一个“类似 servlet”的概念,我不希望具体的类能够看到 System.Web.UI.Page 基础的内部结构。

回答by Chris Karcher

No, public inheritance only.

不,只有公共继承。

回答by Daren Thomas

You probably want a ServletContainer class that gets hooked up with a NServlet implementation. In my book, not allowing private / protected inheritance is not really a big deal and keeps the language less confusing - with LINQ etc. we allready have enough stuff to remember.

您可能想要一个与 NServlet 实现挂钩的 ServletContainer 类。在我的书中,不允许私有/受保护的继承并不是什么大问题,并且可以使语言不那么混乱——使用 LINQ 等,我们已经有足够的东西要记住了。

回答by Scott Dorman

No it doesn't. What would the benefit be of allowing this type of restriction?

不,它没有。允许这种类型的限制有什么好处?

回答by bdukes

You can hide inherited APIs from being publicly visible by declaring that same member in your class as private, and using the new keyword. See Hiding through Inheritancefrom MSDN.

您可以通过将类中的同一成员声明为私有并使用 new 关键字来隐藏继承的 API 使其不公开可见。请参阅MSDN 中的通过继承隐藏

回答by Joel Martinez

If you want the NServlet class to not know anything about the Page, you should look into using the Adapter pattern. Write a page that will host an instance of the NServlet class. Depending on what exactly you're doing, you could then write a wide array of classes that only know about the base class NServlet without having to pollute your API with asp.net page members.

如果您希望 NServlet 类不知道有关 Page 的任何信息,您应该考虑使用 Adapter 模式。编写一个页面来承载 NServlet 类的实例。根据您的具体操作,您可以编写大量仅了解基类 NServlet 的类,而不必使用 asp.net 页面成员污染您的 API。

回答by Brian Stewart

C# allows public inheritance only. C++ allowed all three kinds. Public inheritance implied an "IS-A" type of relationship, and private inheritance implied a "Is-Implemented-In-Terms-Of" kind of relationship. Since layering (or composition) accomplished this in an arguably simpler fashion, private inheritance was only used when absolutely required by protected members or virtual functions required it - according to Scott Meyers in Effective C++, Item 42.

C# 只允许公共继承。C++ 允许所有三种。公共继承暗示了“IS-A”类型的关系,而私有继承暗示了“Is-Implemented-In-Terms-Of”类型的关系。由于分层(或组合)以一种可以说更简单的方式实现了这一点,因此私有继承仅在受保护成员绝对需要或虚函数需要时才使用 - 根据 Effective C++,Item 42 中的 Scott Meyers。

My guess would be that the authors of C# did not feel this additional method of implementing one class in terms of another was necessary.

我的猜测是 C# 的作者不认为这种将一个类实现为另一个类的额外方法是必要的。

回答by Chris Karcher

@bdukes: Keep in mind that you aren't trulyhiding the member. E.g.:

@bdukes:请记住,您并没有真正隐藏该成员。例如:

class Base
{
   public void F() {}
}
class Derived : Base
{
   new private void F() {}
}

Base o = new Derived();
o.F();  // works

But this accomplishes the same as private inheritance in C++, which is what the questioner wanted.

但这与 C++ 中的私有继承实现相同,这正是提问者想要的。

回答by Nick Alexeev

No it doesn't. What would the benefit be of allowing this type of restriction?

不,它没有。允许这种类型的限制有什么好处?

Private and protected inheritance is good for encapsulation (information hiding). Protected* inheritance is supported in C++, although it isn't in Java. Here's an example from my project where it would be useful.

私有和受保护的继承有利于封装(信息隐藏)。C++ 支持 Protected* 继承,但 Java 不支持。这是我的项目中的一个示例,它很有用。

There is a base class in as 3rd party framework**. It has dozens of settings plus properties and methods for manipulating them. The base class doesn't make a lot of checking when individual settings are assigned, but it will generate an exception later if it encounters an unacceptable combination.

第 3 方框架中有一个基类**。它有许多设置以及用于操作它们的属性和方法。基类在分配单个设置时不会进行大量检查,但是如果遇到不可接受的组合,它将在稍后生成异常。

I'm making a child class with methods for assigning these settings (e.g. example, assigning carefully crafted settings from a file). It would be nice to deny the rest of the code (outside my child class) the ability to manipulate individual settings and mess them up.

我正在创建一个带有分配这些设置的方法的子类(例如,从文件中分配精心制作的设置)。拒绝其余代码(在我的子类之外)操纵单个设置并将它们弄乱的能力会很好。

That said, I think in C++ (which, again, supports private and protected inheritance) it's possible to cast the child class up to parent and get access to parent's public members. (See also Chris Karcher's post) Still, protected inheritance improves information hiding. If members of a class B1 need to be truly hidden within other classes C1 and C2, it can be arranged by making a protected variable of a class B1 within C1 and C2. Protected instance of B1 will be available to children of C1 and C2. Of course, this approach by itself doesn't provide polymorphism between C1 and C2. But polymorphism can be added (if desired) by inheriting C1 and C2 from a common interface I1.

也就是说,我认为在 C++ 中(同样支持私有和受保护的继承),可以将子类转换为父类并访问父类的公共成员。(另请参阅Chris Karcher 的帖子) 尽管如此,受保护的继承改进了信息隐藏。如果类B1的成员需要真正隐藏在其他类C1和C2中,可以通过在C1和C2中制作一个类B1的保护变量来安排。B1 的受保护实例将可供 C1 和 C2 的孩子使用。当然,这种方法本身并不提供 C1 和 C2 之间的多态性。但是可以通过从公共接口 I1 继承 C1 和 C2 来添加多态性(如果需要)。

*** For brevity will use "protected" instead of "private and protected".

*** 为简洁起见,将使用“受保护”而不是“私有和受保护”。

** National Instruments Measurement Studio in my case.

** 就我而言是 National Instruments Measurement Studio。

  • Nick
  • 缺口

回答by ulatekh

I know this is an old question, but I've run into this issue several times while writing C#, and I want to know...why not just use an interface?

我知道这是一个老问题,但我在编写 C# 时遇到过几次这个问题,我想知道......为什么不直接使用接口?

When you create your subclass of the 3rd party framework's class, also have it implement a public interface. Then define that interface to include only the methods that you want the client to access. Then, when the client requests an instance of that class, give them an instance of that interface instead.

当您创建第 3 方框架类的子类时,还要让它实现一个公共接口。然后定义该接口以仅包含您希望客户端访问的方法。然后,当客户端请求该类的实例时,改为为他们提供该接口的实例。

That seems to be the C#-accepted way of doing these sorts of things.

这似乎是 C# 接受的做这些事情的方式。

The first time I did this was when I realized that the C# standard library didn't have a read-only variant of a dictionary. I wanted to provide access to a dictionary, but didn't want to give the client the ability to change items in the dictionary. So I defined a "class DictionaryEx<K,V,IV> : Dictionary<K,V>, IReadOnlyDictionary<K,IV> where V : IV" where K is the key type, V is the real value type, and IV is an interface to the V type that prevents changes. The implementation of DictionaryEx was mostly straightforward; the only difficult part was creating a ReadOnlyEnumerator class, but even that didn't take very long.

我第一次这样做是当我意识到 C# 标准库没有字典的只读变体时。我想提供对字典的访问,但不想让客户端能够更改字典中的项目。所以我定义了一个“class DictionaryEx<K,V,IV> : Dictionary<K,V>, IReadOnlyDictionary<K,IV> where V : IV”,其中 K 是键类型,V 是实值类型,IV 是防止更改的 V 类型的接口。DictionaryEx 的实现大多很简单;唯一困难的部分是创建一个 ReadOnlyEnumerator 类,但即使这样也不需要很长时间。

The only drawback I can see to this approach is if the client tries to dynamically cast your public interface to the related subclass. To stop this, make your class internal. If your client casts your public interface to the original base class, I think it'd be pretty clear to them that they're taking their life in their own hands. :-)

我可以看到这种方法的唯一缺点是客户端是否尝试将您的公共接口动态转换为相关子类。要阻止这种情况,请将您的课程设置为内部课程。如果您的客户将您的公共接口转换为原始基类,我认为他们很清楚他们正在自己掌握自己的生命。:-)

回答by franckspike

First solution:

第一个解决方案:

protected internalacts as public in the same assembly and protected on other assemblies.

受保护的内部在同一程序集中作为公共行为并在其他程序集中受到保护。

You would need to change the access modifier of each members of the class which are not to be exposed through inheritance.

您需要更改不会通过继承公开的类的每个成员的访问修饰符。

It is a bit restrictive though that this solution requires and forces the class to be inheritedto be used by another assembly. Thus the choice of being used only by inheritance or not is taken by the unknowing parent... normally the children are more knowing of the architecture...

尽管此解决方案需要并强制继承该类以供另一个程序集使用,但这有点限制。因此,是否仅通过继承使用的选择由不知情的父母决定……通常孩子们更了解架构……

Not a perfect solution but might be a better alternative to adding an interface to hide methodsand still leaving the possibility of using the parent methods to be hidden though the child class because you might not easily be able to force the use of the interface.

不是一个完美的解决方案,但可能是添加接口以隐藏方法的更好替代方案,并且仍然保留使用父方法的可能性通过子类隐藏,因为您可能无法轻易强制使用接口。



Problem:

问题:

The protectedand privateaccess modifiers cannotbe used for methods that are implementing interfaces. That means that the protected internal solution cannot be used for interface implemented methods. This is a big restriction.

保护私有访问修饰符不能被用于那些方法实现荷兰国际集团的接口。这意味着受保护的内部解决方案不能用于接口实现的方法。这是一个很大的限制。



Final solution:

最终解决方案:

I fell back to the interfacesolution to hide methods.

我又回到了隐藏方法界面解决方案。

The problem with it was to be able to force the use of the interface so that members to be hidden are ALWAYS hidden and then definitely avoiding mistakes.

它的问题是能够强制使用接口,以便隐藏的成员始终隐藏,然后绝对避免错误。

To force using only the interface, just make the constructors protectedand add a static method for construction(I named it New). This static New method is in fact a factory function and it returns the interface. So the rest of the code has to use the interface only!

强制仅使用 interface,只需将构造函数设置为 protected添加一个用于构造的静态方法(我将其命名为 New)。这个静态的 New 方法实际上是一个工厂函数,它返回接口。所以剩下的代码只能使用接口了!