“公开” 是否嵌套类
假设我有一个“应用程序”类。 为了进行初始化,需要在构造函数中进行某些设置。 我们还假设设置的数量如此之多,以至于必须将它们放在自己的类别中。
比较此场景的以下两个实现。
实施 1:
class Application
{
Application(ApplicationSettings settings)
{
//Do initialisation here
}
}
class ApplicationSettings
{
//Settings related methods and properties here
}
实施 2:
class Application
{
Application(Application.Settings settings)
{
//Do initialisation here
}
class Settings
{
//Settings related methods and properties here
}
}
对我来说,第二种方法是非常可取的。 它更具可读性,因为它强烈强调两个类之间的关系。 当我编写代码在任何地方实例化 Application 类时,第二种方法看起来更漂亮。
现在想象一下,Settings 类本身也有一些类似的“相关”类,而该类也同样如此。 只有三个这样的级别,类命名在“非嵌套”情况下就会失控。 然而,如果你嵌套,事情仍然保持优雅。
尽管存在上述情况,我在 StackOverflow 上看到有人说嵌套类只有在外部世界不可见的情况下才是合理的; 也就是说,如果它们仅用于包含类的内部实现。 最常见的反对意见是包含类的源文件的大小膨胀,但部分类是该问题的完美解决方案。
我的问题是,为什么我们对嵌套类的“公开暴露”使用保持警惕? 还有其他反对这种使用的论据吗?
Suppose I have a class 'Application'. In order to be initialised it takes certain settings in the constructor. Let's also assume that the number of settings is so many that it's compelling to place them in a class of their own.
Compare the following two implementations of this scenario.
Implementation 1:
class Application
{
Application(ApplicationSettings settings)
{
//Do initialisation here
}
}
class ApplicationSettings
{
//Settings related methods and properties here
}
Implementation 2:
class Application
{
Application(Application.Settings settings)
{
//Do initialisation here
}
class Settings
{
//Settings related methods and properties here
}
}
To me, the second approach is very much preferable. It is more readable because it strongly emphasises the relation between the two classes. When I write code to instantiate Application class anywhere, the second approach is going to look prettier.
Now just imagine the Settings class itself in turn had some similarly "related" class and that class in turn did so too. Go only three such levels and the class naming gets out out of hand in the 'non-nested' case. If you nest, however, things still stay elegant.
Despite the above, I've read people saying on StackOverflow that nested classes are justified only if they're not visible to the outside world; that is if they are used only for the internal implementation of the containing class. The commonly cited objection is bloating the size of containing class's source file, but partial classes is the perfect solution for that problem.
My question is, why are we wary of the "publicly exposed" use of nested classes? Are there any other arguments against such use?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我觉得还好。 这基本上是构建器模式,并且使用嵌套类效果很好。 它还允许构建器访问外部类的私有成员,这非常有用。 例如,您可以在构建器上有一个 Build 方法,它调用外部类上的私有构造函数,该构造函数采用构建器的实例:
这确保构建外部类实例的唯一方式是通过建设者。
我在 Protocol Buffers 的 C# 端口中使用了非常类似的模式。
I think it's fine. This is basically the builder pattern, and using nested classes works pretty well. It also lets the builder access private members of the outer class, which can be very useful. For instance, you can have a Build method on the builder which calls a private constructor on the outer class which takes an instance of the builder:
That ensures that the only way of building an instance of the outer class is via the builder.
I use a pattern very much like this in my C# port of Protocol Buffers.
您可以使用名称空间来关联...相关的事物。
例如:
与像使用命名空间一样使用类的优点是,您可以选择在调用方使用
using
来缩写事物:如果您使用
Sandwich
类就像Filling
的命名空间一样,您必须使用全名Sandwich.Filling
来引用Filling
。知道了这一点你晚上怎么睡觉呢?
You can use namespaces to relate things that are... related.
For example:
The advantage of this over using classes as if they were namespaces is that you can optionally use
using
on the calling side to abbreviate things:If you use the
Sandwich
class as if it were a namespace forFilling
, you have to use the full nameSandwich.Filling
to refer toFilling
.And how are you going to sleep at night knowing that?
您可能想查看 Microsoft 的说法 关于该主题。 我想说,基本上这是一个风格问题。
You might want to check out what Microsoft has to say on the topic. Basically it's a question of style I'd say.
我有效使用公共嵌套类的另一个实际示例是在 MVC 模式中,当我使用具有 IEnumerable 属性的视图模型时。 例如:
我使用它是因为我不希望在外部重用
Product
类,因为它是仅为包含它的特定视图模型定制的。 但我无法将其设为私有,因为 Products 属性是公共的。Another practical example that I have for a valid use of public nested classes is in MVC pattern when I use a viewmodel with an IEnumerable property. for example:
I use it because I don't want
Product
class to be re-used outside because it is customized only for that specific viewmodel which contains it. But I can't make it private because the Products property is public.我主要使用嵌套类来微调对嵌套和/或容器类的访问。
要记住的一件事是,嵌套类定义基本上是类成员,并且可以访问容器的所有私有变量。
您还可以使用它来控制特定类的使用。
示例:
现在,在这种情况下,如果用户(您的类的)实现了外部类,则他只能访问内部类。
I primarily use nested classes for fine-tuning access to the nested and/or the container class.
One thing to remember is that a nested class definition is basically a class member, and will have access to all the container's private variables.
You can also use this to control usage of a specific class.
Example:
Now, in this case, the user (of your class) can only access the Inner class, if he implements Outer.
我不知道这是否被认为是糟糕的设计,但我创建了一些搜索类,用户调用 Run() 方法,传入一个包含搜索条件的对象。 然后它返回搜索结果对象的集合。
这些 SearchCriteria 和 SearchResult 类除了与 Search 类一起使用之外没有其他用途。 因此,我将它们嵌套在 Search 类下,以表明它们是在一起的。
我必须将嵌套类公开,以便搜索类的客户端可以将 SearchCriteria 传递到搜索类中,以便他们可以获得搜索的结果。
I don't know if this is considered bad design or not, but I've got some search classes I make where a user calls the Run() method, passing in an object that holds search criteria. It then returns a collection of search result objects.
These SearchCriteria and SearchResult classes have no utility outside of using them with the Search class. So I nest them under the Search class to show they go together.
I have to make the nested classes public so the client of the Search class can make the SearchCriteria to pass into the Search class and so they can get the results of the Search.