2008-12-03 80 views
17

假设我有一个类“应用程序”。为了被初始化,它在构造函数中需要一定的设置。我们还假设设置的数量非常多,以至于将它们放置在自己的类中是很有吸引力的。“公共”嵌套类是否

比较此方案的以下两种实现。

实现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上说过,只有当外部世界不可见时,嵌套类才是合理的;也就是说,如果它们仅用于包含类的内部实现。通常引用的反对意见是膨胀了包含类的源文件的大小,但部分类是这个问题的完美解决方案。

我的问题是,为什么我们要警惕“公开暴露”使用嵌套类?还有其他反对这种用法的论据吗?

回答

22

我觉得很好。这基本上是构建器模式,使用嵌套类工作得很好。它还允许构建器访问外部类的私有成员,这可能非常有用。例如,你可以对生成器生成方法,它调用的外部类私有构造这需要建设者的一个实例:

public class Outer 
{ 
    private Outer(Builder builder) 
    { 
     // Copy stuff 
    } 

    public class Builder 
    { 
     public Outer Build() 
     { 
      return new Outer(this); 
     } 
    } 
} 

这保证了建设的一个实例的唯一方式外部类是通过建设者。

我在Protocol Buffers的C#端口中使用了非常像这样的模式。

+0

我最近不得不写一些builder代码,并记得这篇文章。原来这是一个非常有用的方法,所以谢谢。 – 2010-06-12 13:33:53

+0

*“它也让构建者访问外部类的私有成员”*只有明确的引用,正确(我敢肯定它不像Java的内部类中那样是隐含的)。 – samosaris 2017-06-19 17:44:15

0

您可能想查看关于该主题的什么Microsoft has to say。基本上这是一个我会说的风格问题。

+0

.NET不强加Java所做的“每个文件一个(公共)类”规则。他们似乎对程序结构有着截然不同的范例。 WRT只有这一条规则,.NET具有更大的灵活性(如果你愿意的话,它是一个富有表现力的超级集合)。伟大的文章btw。 – samosaris 2017-06-19 19:38:48

0

我主要使用嵌套类来微调对嵌套和/或容器类的访问。

要记住的一件事是,嵌套类定义基本上是一个类成员,并且将有权访问所有容器的私有变量。

您也可以使用它来控制特定类的使用情况。

例子:

public abstract class Outer 
{ 
    protected class Inner 
    { 
    } 
} 

现在,在这种情况下,(类)的用户只能访问内部类,如果他实现外。

+1

Iff可能不是拼写错误,但它*有点多余,因为您在句子中已经有单词“only”。 – phoog 2015-12-21 15:29:30

5

您可以使用命名空间来关联...相关的事物。

例如:

namespace Diner 
{ 
    public class Sandwich 
    { 
     public Sandwich(Filling filling) { } 
    } 

    public class Filling { } 
} 

的这种过度使用类,好像他们是命名空间的好处是,你可以选择使用using主叫方缩写事情:

using Diner; 

... 

var sandwich = new Sandwich(new Filling()); 

如果您使用Sandwich类就好像它是Filling的名称空间一样,必须使用全名Sandwich.Filling来指代Filling

你知道那个晚上怎么睡觉?

0

另一个我有效使用公共嵌套类的实际例子是MVC模式,当我使用IEnumerable属性使用viewmodel。例如:

public class OrderViewModel 
{ 
public int OrderId{ get; set; } 
public IEnumerable<Product> Products{ get; set; } 

public class Product { 
public string ProductName{ get; set; } 
public decimal ProductPrice{ get; set; } 
} 

} 

我使用它,因为我不想Product类,因为它仅包含其特定视图模型定制重复使用外也。但是由于产品属性是公开的,所以我不能将它变为私有。