为什么我的公共类不能扩展内部类?

发布于 2024-09-16 16:21:57 字数 110 浏览 8 评论 0 原文

我真的不明白。

如果基类是抽象的,并且仅用于为程序集中定义的公共子类提供通用功能,为什么不应该将其声明为内部?

我不希望抽象类对程序集外部的代码可见。我不想让外部代码知道它。

I really don't get it.

If the base class is abstract and only intended to be used to provide common functionality to public subclasses defined in the assembly, why shouldn't it be declared internal?

I don't want the abstract class to be visible to code outside the assembly. I don't want external code to know about it.

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

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

发布评论

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

评论(5

我不咬妳我踢妳 2024-09-23 16:21:57

更新:这个问题是我 2012 年 11 月 13 日博客的主题。有关此问题的更多想法,请参阅它。感谢您提出的好问题!


你说得对;事实并非一定如此。其他 OO 语言允许“私有继承”,即 D 继承自 B 的事实只能由能够查看 B 的代码利用。

这是原始 C# 设计者的设计决策。不幸的是,我现在不在办公桌旁 - 我要在长周末休息几天 - 所以我面前没有 1999 年的语言设计笔记。如果我回来后想到这一点,我会浏览它们,看看这个决定是否合理。

我个人的看法是继承应该用来表示“是一种”关系;也就是说,继承应该代表用该语言建模的域的语义。我尽量避免将继承用作代码共享机制的情况。正如其他人所提到的,如果您想要表示的是“这个类与其他类共享实现机制”,那么最好选择组合而不是继承。

UPDATE: This question was the subject of my blog on November 13th of 2012. See it for some more thoughts on this issue. Thanks for the great question!


You're right; it doesn't have to be that way. Other OO languages allow "private inheritance", whereby the fact that D inherits from B can only be taken advantage of by code that has the ability to see B.

This was a design decision of the original C# designers. Unfortunately I am away from my desk right now - I'm taking a couple of days off for the long weekend - so I don't have the language design notes from 1999 in front of me. If I think of it when I get back I'll browse them and see if there is a justification for this decision.

My personal opinion is that inheritance should be used to represent "is a kind of" relationships; that is, inheritance should represent the semantics of the domain being modelled in the language. I try to avoid situations where inheritance is used as a code sharing mechanism. As others have mentioned, it's probably best to prefer composition to inheritance if what you want to represent is "this class shares implementation mechanisms with other classes".

热风软妹 2024-09-23 16:21:57

通过从类继承,您可以通过子类公开基类的功能。

由于子类比其父类具有更高的可见性,因此您将公开原本受保护的成员。

您不能通过实现具有更高可见性的子类来违反父类的保护级别。

如果基类确实要由公共子类使用,那么您还需要将父类设为公共。

另一种选择是将您的“父级”保留在内部,使其成为非抽象的,并使用它来组成您的子类,并使用接口强制类实现功能:

public interface ISomething
{
    void HelloWorld();
}

internal class OldParent : ISomething
{
    public void HelloWorld(){ Console.WriteLine("Hello World!"); }
}

public class OldChild : ISomething
{
    OldParent _oldParent = new OldParent();

    public void HelloWorld() { _oldParent.HelloWorld(); }
}

By inheriting from a class, you expose the functionality of the base class through your child.

Since the child class has higher visibility than its parent, you would be exposing members that would otherwise be protected.

You can't violate the protection level of the parent class by implementing a child with higher visibility.

If the base class is really meant to be used by public child classes, then you need to make the parent public as well.

The other option is to keep your "parent" internal, make it non-abstract, and use it to compose your child classes, and use an Interface to force classes to implement the functionality:

public interface ISomething
{
    void HelloWorld();
}

internal class OldParent : ISomething
{
    public void HelloWorld(){ Console.WriteLine("Hello World!"); }
}

public class OldChild : ISomething
{
    OldParent _oldParent = new OldParent();

    public void HelloWorld() { _oldParent.HelloWorld(); }
}
奈何桥上唱咆哮 2024-09-23 16:21:57

我认为您可以做的最接近的事情是通过将其构造函数设置为内部来防止其他程序集创建抽象类,引用自 MSDN

内部构造函数可防止抽象类被用作与抽象类不在同一程序集中的类型的基类。

然后,您可以尝试将 EditorBrowsableAttribute 添加到该类中尝试从 IntelliSense 中隐藏它(不过,老实说,我使用它得到了混合结果)或将基类放入嵌套命名空间中,例如 MyLibrary.Internals ,以将其与其余部分分开你的课程。

I think the closest thing you can do is prevent other assemblies creating the abstract class by making its constructor internal, to quote from MSDN:

An internal constructor prevents the abstract class from being used as the base class of types that are not in the same assembly as the abstract class.

You can then try adding an EditorBrowsableAttribute to the class to try and hide it from IntelliSense (though, I've had mixed results using it to be honest) or put the base class in a nested namespace, such as MyLibrary.Internals to seperate it from the rest of your classes.

请别遗忘我 2024-09-23 16:21:57

我认为你在这里混淆了问题,实际上 C# 是罪魁祸首(还有之前的 Java)。

继承应该作为一种分类机制,而它通常用于代码重用。

对于代码重用,众所周知,组合胜过继承。 C# 的问题在于,它为我们提供了如此简单的继承方法:

class MyClass : MyReusedClass { }

但是为了组合,我们需要自己完成:

class MyClass {
  MyReusedClass _reused;
  // need to expose all the methods from MyReusedClass and delegate to _reused
}

缺少的是像 trait (pdf),这将使组合达到与继承相同的可用性级别。

有关于 C# 中的特征 (pdf) 的研究,它看起来像这样:

class MyClass {
  uses { MyTrait; }
}

虽然我想看到另一个模型( Perl 6 角色)。

更新:

顺便说一句,Oxygene 语言有一项功能 允许您将接口的所有成员委托给实现该接口的成员属性:

type
  MyClass = class(IReusable)
  private
    property Reused : IReusable := new MyReusedClass(); readonly;
      implements public IReusable;
  end;

在这里,IReusable 的所有接口成员都将通过 MyClass 公开,并且它们都将委托给 Reused 属性。不过,这种方法存在一些问题

另一个更新:

我已经开始在 C# 中实现这个自动组合概念:看看 NRoles

I think you're mixing concerns here, and C# is to blame, actually (and Java before it).

Inheritance should serve as a categorization mechanism, whereas it's often used for code reuse.

For code reuse it's always been known that composition beats inheritance. The problem with C# is that it gives us such an easy way to inherit:

class MyClass : MyReusedClass { }

But in order to compose, we need to do it by ourselves:

class MyClass {
  MyReusedClass _reused;
  // need to expose all the methods from MyReusedClass and delegate to _reused
}

What's missing is a construct like a trait (pdf), which will bring composition to the same usability level as inheritance.

There's research about traits in C# (pdf), and it would look something like this:

class MyClass {
  uses { MyTrait; }
}

Although I'd like to see another model (that of Perl 6 roles).

UPDATE:

As a side note, the Oxygene language has a feature that lets you delegate all members of an interface to a member property that implements that interface:

type
  MyClass = class(IReusable)
  private
    property Reused : IReusable := new MyReusedClass(); readonly;
      implements public IReusable;
  end;

Here, all interface members of IReusable will be exposed through MyClass and they'll all delegate to the Reused property. There are some problems with this approach, though.

ANOTHER UPDATE:

I've begun implementing this automatic composition concept in C#: take a look at NRoles.

不寐倦长更 2024-09-23 16:21:57

我认为这会违反里氏替换原则

在这种情况下,我使用了内部类,并且更喜欢组合而不是继承。您的设计是否禁止在内部类中包含所有此类功能,然后让您的公共类包含此内部类的实例?

I think this would violate the Liskov Substitution Principle.

In cases like this, I have used internal classes and prefer composition over inheritance. Is there anything about your design that prohibits containing all such functionality in your internal class, and then have your public classes contain an instance of this internal class?

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