http://hisea.me/p/ruby-story-ep0
随着 Ruby/Rails 的逐渐火热,越来越多的开发人员转向 Ruby.
Rails 简单易用,很多其他语言开发人员很快就做出简单的 Web App.
然而另一方面,Ruby 做为一个语言,确需要一些学习和研究才能掌握其方方面面。
本系列就是专注于提供一些关于 Ruby 语言和其元编程技巧的文章。
在编写这个系列文章的时候,Hisea 对读者做了以下的一些假设:
Ruby 是一个开源的动态类型,强类型,动态的,面向对象的解释型语言。
看上去貌似很麻烦,这些形容词拿出来一个一个解释就很简单了。
开源的:
Ruby 开源协议 1.9.3 以前是 GPLv2 和 Ruby, 1.9.3 之后是 Simplfied BSD 和 Ruby 协议
动态类型:
类型的检查是运行时进行的,相对于 Java 等静态类型语言,类型检查是在编译时进行的
强类型语言:
不同数据类型在操作和运算中出现混用时,除非显示转换类型,否则会报类型错误,相对于 JavaScript 等弱类型语言,不存在类似的限制。
动态语言: 动态语言的定义还很模糊,很多人把动态语言跟动态类型语言搞混,对于 Hisea 来说,动态语言就是类,方法,及其他定义可以在运行时进行改变,元编程就是利用这一特性。由此可见,动态语言跟动态类型语言并不是一个概念。
面向对象:
不解释
解释型: 区别于编译型语言。
Ruby 的动态特性跟以往的静态类型语言相比,需要很多思维上的转换。
如果带着以往的静态语言思维来学习 Ruby,往往需要走些弯路。
对于有其他语言基础的初学者,有些已经练好的武功最好一开始彻底忘掉,才能更好的练成盖世 Ruby 神功。
下面是一些学习 Ruby 需要深刻在心的概念,很多可能跟你现有的思维定式相违背。最好的办法就是清空现有想法,不带偏见的从 0 开始学习 Ruby.
Ruby 里的一切,一切一切,无论是色还是空,都是对象。 不象 Java,Ruby 没有原始类型。1 是对象,1.2 是对象,nil 是对象,true/false 是对象。 类是对象,module 也是对象。
Ruby 界有条谚语,如果你扭的像个鸭子,叫的像个鸭子,你就是个鸭子。
这是 Ruby Duck Typing 的特性。看上去很简单,但是真正把这句话融入到骨髓却不是件易事。如果你在代码中有很多检查类型的判断,例如 is_a, kind_of 等方法,甚至太多的 nil 检测,都是没有很好的理解动态类型的特征。
这一条其实是第一条的延续。很多有多年Java或者C++/C#经验的开发人员(包括Hisea自己),在设计复杂的系统时,都会很自然的想到继承和接口(Interface).在Ruby中设计继承时需要认真的思考一下几个问题。
class 飞行器
def 起飞
fail "子类包含具体的实现!"
end
end
class 飞机 < 飞行器
def 起飞
#飞机起飞实现
end
end
class 热气球 < 飞行器
def 起飞
#热气球起飞实现
end
end
但看以上的例子,父类的作用仅仅是定义了 API 的存在,这在 Java 中是非常常见的,可是在 Ruby 中,这个父类其实存在的意义不是特别大。Ruby 更倾向于,任何能起飞 (拥有‘起飞’方法) 的对象都是飞行器,而不是任何继承飞行器的类的对象。
class Post < ActiveRecord::Base
end
Hisea 本人觉得类似 Mongoid 的 Mixin 方式更适合解决类似的问题。Post 从设计逻辑上来讲,跟 ActiveRecord::Base 没有半毛钱关系。继承关系完全用于分享代码,而在 Ruby 中,更好的分享代码的办法是用 Mixin.
比如第一个例子中,我们可以定义一个飞机的 module,实现 起飞 方法,任何 include 起飞的类,都是某一种飞机。
Ruby 不仅仅是类型是动态的,还有很多其他的也很动态,比如可以动态的 include 或者 extend 一个 module,可以动态的定义或者重新定义一个类,或者一个方法。这在 Java 等静态语言来看是非常的无组织无纪律极其自由散漫。Hisea 面试 Ruby 程序员时经常会问到关于 Metaprogramming 的问题,其实对 Ruby 元编程这个特性懂多懂少并无所谓,只是拿来刺探 Ruby 经验多少的一个问题。资历尚浅的 Ruby 程序员对于元编程总会抱有这样那样的保守想法。
这个话题是 3 的继续,公司新招了一个 Ruby 程序员,他来了一两个星期后问了个问题,问为什么公司 (或者其他 Ruby 程序员) 不爱用 UML 之类的设计工具,当时我也一时找不出答案,后来开车回家的路上用半个小时想明白了,UML 是一个类只见关系的静态表示,Ruby 运行时的情况却是不停在变幻。用静态去表示动态,自然捉襟见肘。
很多从 Java 阵营转来,尤其是有多年 eclipse 经验的 Ruby 初学者尤其是经常爱问,Ruby 用什么 IDE。
得到的回答往往是 text mate,vim,sublime text 2 等等文本编辑器。
很多人可能纳闷,为什么 Ruby/Rails 没有一个 IDE 占领大片江山的情况,为什么 Netbeans/Eclipse 再 Ruby 开发阵营中没有其他语言开发占的地位重要。
其实答案很简单。
IDE 最讨喜的功能是什么?
很多用惯了 IDE 开发的 Java 程序员甚至 XCode 程序员,都会说最爱的功能是代码不全,object 之后按一下'.'立马生成一个方法列表。转到 Ruby 用文本编辑器,没有这个功能,很是郁闷。其实道理很简单,如果方法都是动态生成的,在写程序的时候怎么能给出一个列表呢。
Debugger 还是必要工具么?
静态语言开发,调试是居家旅行杀人灭口必备良药。而 IDE 又是调试的好帮手。
Ruby/Rails 的 Debugger 还没那么成熟,而且如果用 logger, raise 在适当的地方输出 inspect, to_yaml 等内容,也可以很容易的找到错误。
Eclipse 可以很好的配置 Java 开发环境。 Ruby/Rails有好用的RVM,RubyGems,Bundler.
所以,不补全,不调试,不配环境,要 IDE 不也是拿来当文本编辑器用么。
零零总总的想了些 Ruby 的主要特性,以及常见的初学者的疑问/误区。
本文打算从这里开始,写点 Ruby 深层次的一些概念和特性,并且怎么利用这些特性进行 Metaprogramming.
下回注重一些对象 Object 的故事。
如果你有任何问题,欢迎讨论。
作者:Hisea
web: http://hisea.me
email: [email protected]
weibo: http://www.weibo.com/zyinghai
twitter: https://twitter.com/zyinghai
github: https://github.com/hisea
Hisea.me 版权所有