1. 第一个Ruby程序
今天的第一道程序不是Hello World
。而是定义一个类。
class Greeting
def initialize(text)
@text = text
end
def welcome()
@text
end
end
# 创建一个Greeting类的实例
my_object = Greeting.new "Hello"
p my_object.class
p my_object.class.instance_methods(false)
p my_object.instance_variables
上面的代码我们定义了一个类Greeting
,并且创建对象,在后面运用内省
的机制访问
- 对象所属的类。
- 类中含有的实例方法。
- 实例变量。
打印结果如下:
Greeting
[:welcome]
[:@text]
跟Python的一点不同,Ruby中函数调用是可以忽略()
的,而Python里面只有print
语句是不需要加入()
,(Python3已经修复了这个问题,必须要加上()
.)。-_-其实那时候我选Python2就是因为看到方法调用不需要加括号我就果断选了Python2了。
不过考虑到可读性,建议,如果是调用带有参数的方法调用都加入括号。
2. Ruby的各种命名简解
Ruby中的变量定义(Learn from Perl)
- $开头:全局变量
- @开头:实例变量
- @@开头:类变量, 类变量被共享在整个继承链中
- 大写字母开头:常数
这个规则是从Perl语言来的启发。通过特殊符号来区分不同类型的变量有助于提高程序的可读性。
规定类名和模块名必须首字母大写
由于在Ruby里面类名一旦定义便一般不会再修改。所以它的机制是认为命名应该是常量。否则会报错。
# 定义小写字母开头的模块名
ruby(main):018:0> module a
ruby(main):019:1> end
SyntaxError: (ruby):18: class/module name must be CONSTANT
from /usr/bin/ruby:12:in `<main>'
# 定义小写字母开头的类名
ruby(main):020:0> class a
ruby(main):021:1> end
SyntaxError: (ruby):20: class/module name must be CONSTANT
from /usr/bin/ruby:12:in `<main>'
# 如果对一个常量进行赋值的话会报警告。但是还是可以修改
ruby(main):023:0> RU = 2
=> 2
ruby(main):024:0> RU =12
(ruby):24: warning: already initialized constant RU
(ruby):23: warning: previous definition of RU was here
=> 12
方法名也可以带特殊符号
Ruby 的方法命名是可以带一些特殊的符号。(这个特性据说是从Lisp学的)。
我们最熟悉的判断一个数是奇数还是偶数:
[9] pry(main)> a = 12
=> 12
[10] pry(main)> a.even?
=> true
由于在Ruby里面一切都是对象,所以这里的12甚至可以直接调用
[30] pry(main)> 12.even?
=> true
这里很有意思的是方法名可以加上问号,这可以用来识别一些返回true
or false
的方法。团队合作的时候一看,就知道这个方法是用来进行逻辑判断的。这也挺好的。不过只能放在最后面。
这样的事情发生在Python里面就很不可思议了。Python方法名是不接受这类定义的。
3. 链条式的调用
Ruby是一门十分灵活的语言,又得益于它的不需要括号来调用函数的特性,我们可以写出这种代码
[37] pry(main)> a = "heng"
=> "heng"
[38] pry(main)> a.methods.grep /cat/
=> [:concat]
这里是要查找出字符串里面的所有方法中包含关键字cat
的方法名(返回的是一个数组),这里用了正则匹配。这是一个我比较喜欢的地方。 而像 a.methods.grep
顺着读,没有括号在中间的那种违和感。感觉就是在读英文。由于这种简练语法这门语言在国外有不少的爱好者。
当然grep
只是数组的内置函数
[40] pry(main)> a.methods.class
=> Array
[41] pry(main)> Array.instance_methods.grep /grep/
=> [:grep]
所以只要返回的是对象,并且参数是可以为空的话,这条链可以很长很长。
比如你要看字符串类型的祖先可以这样。
[42] pry(main)> string = "I'm String"
=> "I'm String"
[45] pry(main)> string.class
=> String
[46] pry(main)> string.class.superclass
=> Object
[47] pry(main)> string.class.superclass.superclass
=> BasicObject
[48] pry(main)> string.class.superclass.superclass.superclass
=> nil
这个BaseObject
是Ruby里面最基本的类了。人们叫他白板类
。它的实例方法只有很少的几个。不过在某些环境下是十分有用的。
[12] pry(main)> BasicObject.instance_methods
=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__, :__binding__]
如果再继续就会报错了。因为nil
的superclass
会抛出异常。
NoMethodError: undefined method `superclass' for nil:NilClass
from (pry):52:in `__pry__'
这个错误看似没用
。其实会触发一些很好玩的机制。Ruby设置了不少的钩子,我们通过这些钩子可以做很多好玩的事情,这在后面介绍动态方法
的时候会继续拓展。