1. load_path, require, load, include
load_path相当于java的class path
require和load相当于java的import,但load和require是有区别的。
1. require不需要指定文件后缀,而load需要。
2. require会track所有已经require的文件,不会对同一个文件require两次。而load每次都会重新load文件。
那么load用在哪里呢?在有些场合load是有用的,比如rails的developmeng环境,每次都需要load最新的文件,以保证程序运行在最新的代码之上。
include用于做mixin。
2. namespace
无论如何,要避免conflict的namespace。 Ruby Namespace Conflicts
3. block
class JukeboxButton < Button
def initialize(label, &action)
super(label)
@action = action
end
def buttonPressed
@action.call(self)
end
end
bStart = JukeboxButton.new("Start") { songList.start }
bPause = JukeboxButton.new("Pause") { songList.pause }
注意initialize方法的最后一个参数:如果一个方法的最后一个参数前面带有&符号,那么当方法被调用时,会去寻找是否有一个block可 以被调用。注意到在initialize方法中,block被转化成一个Proc对象,赋值给@action实例变量。当buttonPressed方法 被调用时,会调用@action的call方法,以调用这个Proc对象。
Block或者Proc对象不仅仅是一团代码,跟这个block(当然proc对象也一样)关联的还有所有这个block定义之处的所有上下文:self,方法,变量等等。
4. method_missing
When you send a message to an object, the object executes the first method it finds on its method lookup path with the same name as the message. If it fails to find any such method, it raises a NoMethodError exception - unless you have provided the object with a method called method_missing . The method_missing method is passed the symbol of the nonexistent method, and any arguments that were passed in.
这就是machinist里Sham的实现方式。要注意的是,如果你想捕获的是class method,那么你要定义一个self.method_missing方法。
5. public protected private
With no arguments, sets the default visibility for subsequently defined methods to public . With arguments, sets the named methods to have public visibility.
Many things in Ruby is just method !
ruby永远不想真的限制你做什么事情,对于protected或者private方法的调用只需object.send(:method_name)即可。
6. What's the binding
Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use. The variables, methods, value of self , and possibly an iterator block that can be accessed in this context are all retained. Binding objects can be created using Kernel#binding , and are made available to the callback of Kernel#set_trace_func .
These binding objects can be passed as the second argument of the Kernel#eval method, establishing an environment for the evaluation.
class Demo
def initialize(n)
@secret = n
end
def getBinding
return binding()
end
end
k1 = Demo.new(99)
b1 = k1.getBinding
k2 = Demo.new(-3)
b2 = k2.getBinding
eval("@secret", b1) #=> 99
eval("@secret", b2) #=> -3
eval("@secret") #=> nil
7. Proc
Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.
def gen_times(factor)
return Proc.new {|n| n*factor }
end
times3 = gen_times(3)
times5 = gen_times(5)
times3.call(12) #=> 36
times5.call(5) #=> 25
times3.call(times5.call(4)) #=> 60
8. system
Executes cmd in a subshell , returning true if the command was found and ran successfully, false otherwise. An error status is available in $?. The arguments are processed in the same way as for Kernel::exec.
system("echo *")
system("echo", "*") # echo "*"
produces:
config.h main.rb
*
9. `
Returns the standard output of running cmd in a subshell. The built-in syntax %x{…} uses this method. Sets $? to the process status.
`date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
`ls testdir`.split[1] #=> "main.rb"
`echo oops && exit 99` #=> "oops\n"
$?.exitstatus #=> 99
10. *
class File
def File.openAndProcess(*args)
f = File.open(*args)
yield f
f.close()
end
end
openAndProcess方法的参数*args意味着:把传入的参数集合成一个数组。
而当调用File.open时,传入*args作为参数,意味着:把传入的数组(args)展开。
11. block_given?
可以用block_given?来做条件判断:
class File
def File.myOpen(*args)
aFile = File.new(*args)
# If there's a block, pass in the file and close
# the file when it returns
if block_given?
yield aFile
aFile.close
aFile = nil
end
return aFile
end
end
同时,对于有yield的方法,如果不传block会出错。所以,可以用block_given?来设条件。
files = Dir["*"]
sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
# so that we can overide one's <=> method to change the sort behaivor.
equals to:
sorted = Dir["*"].sort_by {|f| File.new(a).mtime }
14. File.dirname(__FILE__)
取得当前文件所在的目录
15. Freeze
Prevents further modifications to obj . A TypeError will be raised if modification is attempted. There is no way to unfreeze a frozen object.
16.
class A
VALUE = A.new // it will fail because when run this line, class A is not yet loaded. This is quite
// different with Java.
end
17. ruby的builder库
xmlMarkup,很好地结合使用了block和method_missing.
18. BigDecimal
jruby也有BigDecimal类。
19. Class Variable and Instance Variable
我们对Ruby的class variable和instance variable估计都很熟悉,但可能下面的程序输出结果有点小小出乎你的意料:
class ExampleClass
@@variable = 'class variable'
@variable = 'class instance variable'
def initialize
@variable = 'instance varialbe'
end
def self.test
p @@variable
end
end
example = ExampleClass.new
example.instance_eval do
p @variable
end
ExampleClass.instance_eval do
p @variable
end
ExampleClass.test
p example.instance_variables.inspect
p ExampleClass.instance_variables.inspect
p ExampleClass.class_variables.inspect
output:
"instance variable"
"class instance variable"
"class variable"
"["@variable"]"
"["@variable"]"
"["@@variable"]"
对于class variable和instance variable的区别大家都很清楚。而疑惑点在于“instance variable”和“class instance variable”之间的区别。疑惑的本质还在于对ruby对象模型的不清晰。其实,类ExampleClass本身也是一个对象,它是Class的一个实例。而class instance variable是ExampleClass这个实例的instance variable。
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes
20. extend vs include
http://codeprairie.net/blogs/chrisortman/archive/2007/07/07/ruby-include-and-extend.aspx