《Effective C#》某些地方实在是对不起Effective这个词(I)

翻了一半,到某些地方实在是看不下去了,鉴于这本书的名气和传说中的销售量,这些地方拿出来给大家讨论讨论,对看了这本书而又没发现这些东西的安达应该是有益的.

      条款19:Prefer Defining and Implementing Interfaces to Inheritance。该条款教导我们,尽量定义并实现接口,而不是使用继承。
      实际上,抽象类具有一些接口不可能提供的特点。
      1、接口只是提供了实现类提供的行为,而没有提供这些行为的规范。如:一个调制解调器接口包括:拨号、发送数据、接收数据、挂断这些行为,但是并没有也没办法定义说发送数据之前,必须得先拨号,且拨号必须成功这样的规范;但是抽象类不同,它可以定义它们。
      2、在抽象类中增加一项功能,它的派生类就自动拥有了这些功能;这东西显然通过接口实现不了——在接口中增加一向功能的后果是所有的实现类都得重写,并重新编译。
      在实际项目中,碰到过这种让人非常头痛的情况。所以一般做法是提供接口,然后提供一个实现了这个接口的抽象类。派生类一般情况下是从抽象类派生,而不是直接去实现接口。

      OK,现在我们再来看<Effective C#>中提到的证明使用接口而不使用抽象类的反例:
      

public void PrintCollection( IEnumerable collection )
{
  
foreachobject o in collection )
  Console.WriteLine( 
"Collection contains {0}",
    o.ToString( ) );
}


public void PrintCollection( CollectionBase collection )
{
  
foreachobject o in collection )
  Console.WriteLine( 
"Collection contains {0}",
    o.ToString( ) );
}


      书里面说了
“The second method is far less reusable. It cannot be used with Arrays, ArrayLists, DataTables, Hashtables, ImageLists, or many other collection classes. Coding the method using interfaces as its parameter types is far more generic and far easier to reuse.”大体意思是第二个方法可用性很差劲,它不能使用诸如:Arrays、ArrayLists、DataTables等等,使用第一种使用接口做参数方法就很好,用起来很方便。
      现在的问题是:谁会这么写代码呢?作为一个方法的参数,它可能会有一些限制,比如上述的PrintCollection。对该方法的实现,唯一的限制是它得实现IEnumerable接口,只要入口参数实现了这个接口,方法就可以完成预定义的语义。第二种写法扩大了限制的范围,摆明了后果就是可用性降低。
      定义一个方法的入口参数类型,一个很重要的原则就是:最小限制化。
      该原则同样适用于泛型类和泛型方法的定义。

      它后面的例子犯的错误如出一辙。

      吃饭时间到了,其他的忽悠稍后。^_^


-- 补充点东西,见文《补》

posted on 2007-07-19 11:31  Nineteen@newsmth  阅读(2165)  评论(28编辑  收藏  举报

导航