现在回过头来看看我们做了什么。我们先写了个很有用的函数total_size(),它包含了一段遍历目录结构的代码,对于其他应用程序来说,这段代码也十分实用。因此,为了让total_size()更加通用,我们将所有跟计算大小有关的部分都提取出来,替换成调用用户指定的任意函数的处理。其结果就是dir_walk()。这样,对于任何需要遍历目录结构并做某些处理的程序,dir_walk()负责处理遍历,而参数中的函数负责做特定的处理。只要给dir_walk()传递适当的参数,就能让它按照我们的希望来运行。通过提取有用部分,并给它两个函数参数,我们获得了灵活性,同时也有机会重用dir_walk()的代码。这就是函数式编程的核心思想。
而面向对象(Object-oriented,简称OO)式编程现在正备受关注。面向对象编程的目标与函数式编程相同,都是通过将软件划分成通用的部件,来增加组件的可重用性。
在面向对象系统中,可以用类似的方法变换total_size()函数,但会得到不同的结果。total_size()将变成抽象的基类,对应于负责遍历目录的对象,这些对象将会有个名为dir_walk()的方法,而它会依次调用两个尚未定义的虚方法file和directory。(用C++术语来说,这种方法称为纯虚方法)。这种类本身毫无用武之地,因为并没有定义file和directory方法。要使用该类,必须创建一个子类,其中定义file和directory方法,然后创建该子类的对象。这些对象都将继承同样的dir_walk方法。
本例中,我认为函数式编程提供的轻量化解决方案更容易使用,并且,作为参数的函数能够在使用时定义,而无需放在类文件里。但重要的是,尽管风格不同,但将原始函数分解成组件的方法却分毫不差。函数式使用了函数参数,面向对象使用了纯虚方法。尽管本书其余部分都在讨论函数式编程,但大部分技巧也可以直接应用在面向对象编程中。