并不是所有的人都须要知道所有的事。也不是所有的类型须要是公共的。对于每个类型,在满足功能的情况下,应该尽可能的限制访问级别。而且这些访问级别往往比你想像的要少得多。在一个私有类型上,所有的用户都可以通过一个公共的接口来访问这个接口所定义的功能。
让我们回到最根本的情况上来:强大的工具和懒惰的开发人员。VS.net对于他们来说是一个伟大的高产工具。我用VS.net或者C# Builder轻松的开发我所有的项目,因为它让我更快的完成任务。其中一个加强的高产工具就是让你只用点两下按钮,一个类就创建了,当然如果这正是我想要的话。VS.net为我们创建的类就是这样的:
public class Class2
{
public Class2()
{
//
// TODO: Add constructor logic here
//
}
}
这是一个公共类,它在每个使用我的程序集的代码块上都是可见的。这样的可见级别太高了,很多独立存在的类都应该是内部(internal)的。你可以通过在已经存在的类里嵌套一个受保护的或者私有的类来限制访问。 越低的访问级别,对于今后的更新整个系统的可能性就越少。越少的地方可以访问到类型,在更新时就越少的地方要修改。
只暴露须要暴露的内容,应该通过尝试在类上实现公共接口来减少可见内容。你应该可以在.Net框架库里发现使用Enumerator模式的例子,System.ArrayList包含一个私有类,ArrayListEnumerator, 而就是它只实现了IEnumerator接口:
// Example, not complete source
public class ArrayList: IEnumerable
{
private class ArraylistEnumerator : IEnumerator
{
// Contains specific implementation of
// MoveNext( ), Reset( ), and Current.
}
public IEnumerator GetEnumerator()
{
return new ArrayListEnumerator( this );
}
// other ArrayList members.
}
对于我们这样的使用者来说,不须要知道ArrayListEnumerator类,所有你须要知道的,就是当我们在ArrayList对象上调用GetEnumerator函数时,你所得到的是一个实现了IEnumerator接口的对象。而具体的实现则是一个明确的类。.Net框架的设计者在另一个集合类中使用了同样的模式:哈希表(Hashtable)包含一个私有的HashtableEnumerator, 队列(Queue)包含一个QueueEnumerator, 等等。私有的枚举类有更多的优势。首先,ArrayList类可以完全取代实现IEnumerator的类型,而且你已经成为一个贤明的程序员了,不破坏任何内容。其实,枚举器类不须要是CLS兼容的,因为它并不是公共的(参见原则30)。而它的公共接口是兼容的。你可以使用枚举器而不用知道实现的类的任何细节问题。
创建内部的类是经常使用的用于限制类型可见范围的概括方法。默认情况下,很多程序员都总是创建公共的类,从来不考虑其它方法。这是VS.net的事。我们应该取代这种不加思考的默认,我们应该仔细考虑你的类型会在哪些地方使用。它是所有用户可见的?或者它主要只是在一个程序集内部使用?
通过使用接口来暴露功能,可以让你更简单的创建内部类,而不用限制它们在程序集外的使用(参见原则19)。类型应该是公共的呢?或者有更好的接口聚合来描述它的功能?内部类可以让你用不同的版本来替换一个类,只要在它们实现了同样的接口时。做为一个例子,考虑这个电话号码验证的问题:
public class PhoneValidator
{
public bool ValidateNumber( PhoneNumber ph )
{
// perform validation.
// Check for valid area code, exchange.
return true;
}
}