• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

《Effective Ruby:改善Ruby程序的48条建议》一第9条:提防Ruby最棘手的解析 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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

第9条:提防Ruby最棘手的解析

说到命名规则,Ruby给了我们很大的自由。肃然不像Lisp那样的语言一样自由,但Ruby允许我们在方法末尾使用三个字母数字以外的符号:“?”、“!”和“=”。三个字符中的两个具有纯粹的美感,而另一个在Ruby中有特殊的含义。

如你所知,以问号结束的方法名既不会改变任何事情,也不会使Ruby对它特殊对待。这仅仅是一个为Ruby程序员所接受的命名惯例,以此来说明方法将返回一个布尔值。(要知道什么是Ruby中的布尔值,请参见第1条。)这个命名惯例并不是强制的,并且以“?”结尾的方法仍然可以返回你想要的任何类型的值。感叹号也是类似的,如果有所不同,也只是模糊一点。感叹号常常意味着方法会改变接收者,也可以是对你的示警,表示存在潜在的有害行为。这两种情况都是Ruby程序员指南中不提倡的。以等号结尾的方法则完全不同。
以“=”结尾的方法将变为setter方法,并允许你使用漂亮的语法来调用它。典型场景是,这类方法接受一个参数,改变一些内部状态,并返回它们的参数。这意味着setter方法也能被用作左值(赋值语句的左侧部分)。

即使从技术上讲“=”是方法名的一部分,Ruby却允许我们在等号和方法名的其他部分之间输入空格。这看似是变量赋值,但实质上仅仅是一个普通的方法调用。当你加上括号并去掉空格时你会更清楚地看到这一点。

你可能不曾亲手定义过这些setter方法,但你一定间接地定义过。因为Ruby有一些帮助方法能帮我们做这个事情。attr_writer和attr_accessor都像之前的例子一样定义了类似value=这样的setter方法。这样的迂回可能会让你有点困惑,这也是我提起它们的原因。只要你记住这些帮助方法做的事情以及接下来的建议,任何困难都不是问题。
说到困难,我们得看看赋值和setter之间的区别。由于setter方法的调用看似变量赋值,因此很容易混淆它们。看下面这个例子:

把initialize方法体中的内容当作对counter=方法的调用也不是毫无道理,这也是很多人所假设的。但这当然是不对的,那只是个简单的变量赋值呀。initialize方法创建了一个新的局部变量counter,并将其赋值为0,然后又在作用域结束的时候丢弃了对这个变量的引用。当你仔细思考,会发现这显然不是我们想做的。(如果你像第5条建议的那样启用了警告,Ruby将会在出现这个错误时提醒你。)
Ruby在对变量赋值和对setter方法调用时的解析是有区别的。区别在于,Ruby调用setter方法时要求存在一个显式接收者。为了调用setter方法,而非创建一个变量,你需要预先指定方法名的接收者。因此,在实例方法中调用方法counter=,你需要使用self充当这个接收者。

通过使用self作为接收者,Ruby将正确地解析你的代码并调用counter=这个setter方法,而非创建一个新的变量。你可能会想,如果在调用方法时在等号和方法名的其他部分间不加等号,并用括号包住参数也许可以避免使用self(即,counter=(0)),然而事与愿违,这是无效的。我们在这里被迫显式地使用self作为接收者,但这导致了另一个问题。
被解析规则坑过的程序员倾向于在它们的代码中过分使用不必要的self接收者,这会使代码显得凌乱。在每个方法调用前都加上self从技术角度来说没有问题,但显然它降低了代码的可读性。这显然是Ruby程序员中普遍存在的代码的坏味道。看看你能否在下面的代码中找到无须使用self的地方:

显然,full方法中的self是冗余的。由于没有调用setter方法,你可以安全地移除self并依靠那些简单的解析规则。当Ruby遇到类似f?irst或last的标识符时,它会检查当前作用域中是否存在同名变量。如果不存在,它会把这个标识符作为方法名再次查找。在本例中,对于Name类里的两个属性,Ruby通过早先的attr_accessor找到了它们的getter方法。这里有另一个版本的full方法,与之前的方法做了相同的事情,但去除了噪音:

到此为止,你应该对setter方法的特殊性确信无疑了。如果不想碰到些惊喜,记得调用时指定一个接收者。但是千万别因此让它愚弄了你,并不是所有方法都需要接收者,尤其是在实例方法中调用时。对于每个其他类型的方法,如果没有显式指定方法接收者,Ruby将自动使用self作为接收者。
要点回顾
setter方法在调用时需要显式的接收者。没有接收者时,会被Ruby解析为变量赋值。
在实例方法中调用setter方法时,使用self作为接收者。
在调用非setter方法时,不需要显式指定接收者。换句话说,不要使用不必要的self,那会弄乱你的代码。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
ruby语法_Ruby函数(方法)语法发布时间:2022-07-14
下一篇:
构建基于Ruby的Lambda函数发布时间:2022-07-14
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap