《Effective Ruby:改善Ruby程序的48条建议》一第8条:初始化子类时调用super

简介:

本节书摘来自华章出版社《Effective Ruby:改善Ruby程序的48条建议》一书中的第2章,第2.3节,作者 [美]彼得 J.琼斯(Peter J. Jones),更多章节内容可以访问云栖社区“华章计算机”公众号查看

第8条:初始化子类时调用super

Ruby中,类没有传统的OOP式的构造方法。如果想要控制对象的初始状态,我们得写一个名为initialize的方法并在那里做必要的工作。在一个新对象被分配空间之后,就会在new中调用这个方法。如果你不在自己的类中自定义initialize方法,你的类将从BasicObject类中继承默认实现。不过这并不那么有效。事实上,那是个空方法,什么也没做。它只是在那里,使得new方法在你没有自定义initialize方法时有处可调。还好,很多时候BasicObject#initialize就可以满足你的需要了。不过当你需要自定义initialize方法时是个小例外。
有一点特别容易被忽略,initialize方法其实只是一个常规的私有实例方法,因此它遵循所有常规方法搜索规则。比如,如果你想,你能定义reset方法来简单地调用initialize方法把所有实例变量重设为其初始值。不过把initialize方法作为常规方法调用会造成令人惊讶的结果。当你定义initialize方法时你也重载了所有在继承体系中其他更高层的initialize的定义。如果在你曾用过的语言中存在正式的构造方法,你可能希望所有的继承体系中的方法会链在一起而非相互重载。不过在Ruby中和你想得不太
一样:
image

来看方法Parent#initialize,很容易看出,当创建一个新的Parent对象时,实例变量@name会被初始化为一个默认值。也很容易看出当创建一个Child时,方法Child#initialize会为实例变量@grade赋值。可能不清楚的问题就是,创建一个Child对象是否也能为@name赋初始值。在IRB中运行这些代码就可以搞清楚这个问
题了:
image

啊!Ruby不能自动调用被重载的方法,即使在initialize方法中也不行。本例中Child::new没有调用Parent类里的initialize方法,因为Child类有自己的initialize方法,它重载了父类的这个方法。重写带参的initialize方法将使事情更清楚些。
image

如今你能看到这个窘境了。Ruby没有为我们提供给子类和其超类的initialize方法建立联系的方式。因此没办法知道如何自动调用超类中的initialize方法并传递正确的参数。于是这个任务留给了我们。这对新手Ruby程序员来说是件令人惊讶的事情,甚至老手也会不一定记得。
既然Ruby不会为我们初始化父类,我们该如何完成它呢?为initialize方法准备的解决方案和重载其他方法一样。也就是说,我们可以使用通用意义上的super关键字来调用继承体系中位于高层的方法。
image

在放弃了自动构造方法的同时我们获得了灵活性。使用super调用超类的initialize方法让我们拥有了如何初始化超类以及在什么时候初始化超类的控制权。超类应该在子类之前初始化吗?在初始化超类之前我们需要设置一些环境变量吗?我们可以自由地按照需要安排这些行为。只要记住用super就行,花点时间复习一下super的各种用法吧,见第7条。
在总结之前,我得提醒你initialize不是构建新对象的唯一方式。Ruby允许我们使用dup和clone方法创建对象的副本。当你使用这些方法中任一个时,可以通过定义initialize_copy方法对新创建的副本对象执行一些特别的逻辑。如果你从超类重载initialize_copy方法,你一定想使用super来正确地构建它。
要点回顾
当创建子类对象时,Ruby不会自动调用超类中的initialize方法。作为替代,常规的方法查询规则也适用于initialize方法,只有第一个匹配的副本会被调用。
当为显式使用继承的类定义initialize方法时,使用super来初始化其父类。在定义initialize_copy方法时,应使用相同的规则。

相关文章
|
数据库 开发工具 git
【Ruby on Rails全栈课程】5.4 项目上线--项目初始化
1、数据库初始化 (1)登录数据库,创建名为data_system的database
141 0
|
测试技术 C++ Ruby
C++程序中嵌入Ruby脚本系统
Ruby,一种为简单快捷面向对象编程(面向对象程序设计)而创的脚本语言,由日本人松本行弘(まつもとゆきひろ,英译:Yukihiro Matsumoto,外号matz)开发,遵守GPL协议和Ruby License。
1562 0
|
消息中间件 安全 Ruby
Nanite:Ruby程序的一个自我装配集群
本文讲的是Nanite:Ruby程序的一个自我装配集群,Nanite(由Ezra Zygmuntowicz开发)是Engine Yard云计算策略的一个新兵:它是“Ruby程序的一个自我装配集群”,用以构筑高度可伸缩的Web应用的后端。
1096 0
|
程序员 Ruby
《Effective Ruby:改善Ruby程序的48条建议》一导读
学习一门新的编程语言通常需要经过两个阶段。第一阶段是学习这门编程语言的语法和结构。如果我们具有其他编程语言的经验,这个阶段通常只需要很短的时间。以Ruby为例,接触过其他面向对象语言的程序员对Ruby的语法也会比较熟悉。有经验的程序员对于语言的结构(如何根据语法构建应用程序)是很熟悉的。
1207 0
|
NoSQL 数据库 Ruby
我的第一个Ruby On Rails + MongoDB程序
    最近想进一步学习一下MongoDB,而很久之前使用过ROR,正好也凑个机会重新拾起来。下面是建立第一个项目的过程。        主要参考文档:        1. Rails 3 - Getting started        2.
926 0
|
Apache Ruby Windows
让Apache支持ruby写的cgi程序
ruby apache cgi 配置 1,按说明安装ruby的apache mod 2,配置文件如下: 1 ######################################################### 2 # ruby cgi 配置 3 #######...
760 0
|
Ruby
Ruby On Rails学习笔记(3)——Rails程序由0到1
     正如Rails的理念一样,创建一个新的Rails应用程序的过程非常简单,下面就来看看如何从0到1建立一个全新的Rails应用程序。     1、启动InstantRails,打开其Rails应用程序管理器(Rails Application Manager):         2、创建...
743 0
|
1月前
|
数据采集 Web App开发 数据处理
Ruby网络爬虫教程:从入门到精通下载图片
Ruby网络爬虫教程:从入门到精通下载图片