1.
[].methods == Array.instance_methods //true
[].methods.grep /re/
obj.instance_variables //访问一个对象的所有域
Array.instance_methods //访问一个类的所有实例方法(不是在对象而是在类上调用的)
Array.instance_methods(false)//不显示父类以及include的模块中定义的方法
2.ruby中Class的父类是Module,Class比他多了new和allocate方法。
也就是说完全可以用一个代表另一个。但希望代码被include时候用Module,需要实例化时用Class。
3.
Module.constants 当前系统中的所有顶级类与模块
module A
B = 1
class C;end;
end
A.constants => [:B,:C]
4.ruby对象中的实例变量是独立于对象的,每一个对象都可以有自己的实例变量。
o = Object.new
o.instance_variable_set('@x',10)
o.instance_variable_get('@x')
5.
module A
end
Class O
include A
end
Class P < O;end
P.ancestors => [:P,:O,:A,:Object,:Kernel,:BasicObject] //即查找方法先查找O,再查找A模块里的
当然可以使用 prepend A,这样就会变成[:P,:A,:O,:Object,:Kernel,:BasicObject]
5.*
class A
include B
include C
end
A.ancestors [:A,:C,:B,...]
6.Kernel.private_instance_methods.include? :print => true
所有类都会include Kernel,所有print就到处可以调用了。可以对Kernel进行猴子补丁来加入新的全局函数
gem install awesome_print
ap json_obj,indent:2 //该模块重新打开了Kernel模块,加入了ap方法,用于漂亮打印。
!!需要注意的是,这里为何是Kernel.private_instance_methods呢?因为Kernel是一个模块,是Module类的实例。
Kernel.instance_methods(类和模块本质是一样的)返回的是在Module类中定义的所有方法。
9.private的含义
ruby中private在父类中定义,在子类中也可以调用该方法,和Java截然不同。
实际上,Ruby中private的语义有所不同。
class C
def public_method
self.private_mthod
end
private
def private_method;end
end
C.new.public_method会报错,因为Ruby的private指的是方法只能由同一个对象进行调用,并且
在子类中,只要是同一个receiver,也可以调用父类中的private方法。
另外,private方法同样隐含的推导出了调用此方法时不需要填写接受者(此处为self),而这里使用了self,
违反了“私有规则”,因此把self去除即可运行。
10.类,模块,常量类似于文件系统,类和模块类似于文件夹,普通常量类似于文件
11.
BasicObject类中定义了私有的method_missing方法,子类可以重写他。
undef_method,remove_method
class Animal def hello puts "hello from animal" end end class Person < Animal def hello #子类如果不重复定义hello的话,那么不能调用下面的remove_method方法 puts "hello from person" end remove_method :hello end Person.new.hello //调用父类的hello
12.
ruby在切换作用域时(看到module,class,def关键字),将关闭当前作用域,打开一个新的作用域,
因此Java中得内部作用于(inner scope)在ruby中不使用
<pre name="code" class="ruby">a = 1
class A
puts a //报错
end
为了访问内部作用域,需要使用Class.new,define_method,instance_eval方法
a = 1
c = Class.new do //通过Class.new,我们可以访问外部的a了。
puts "a from class definition:" + a.to_s
def initialize
@v = 123
end
define_method :test do
puts "a from test:" + a.to_s //通过define_method,我们可以访问外部的a了
end
end
c.new.test
c.new.instance_eval do
puts @v + a //通过instance_eval,我们可以访问外部的a了
end
instance_eval,class_eval都可以使得对象内部可以访问外部作用域的变量,当然在instance_eval中还可以直接访问对象的内部属性,如@id。
13.
#代码块是ruby中唯一不是对象的元素,
#想要保存它必须通过以下4种方式将他转化成Proc对象
block1 = Proc.new { |x| x + 1 }
block2 = proc { |x| x + 1 }
block3 = lambda { |x| x + 1 }
block4 = -> (x) {x + 1}
puts block1.call(100)
puts block2.call(100)
puts block3.call(100)
puts block4.call(100)
puts block1.class #Proc
puts block2.class #Proc
puts block3.class #Proc
puts block4.class #Proc
puts block1.lambda? #true
puts block2.lambda? #true
puts block3.lambda? #false
puts block4.lambda? #false
14.
String.class_eval do
def 或者 define_method 添加一个实例方法
end
String.instance_eval do //把String当做一个instance
def或者define_instance_method 添加一个类方法
end
15.
obj = Object.new
def obj.test;end //定义单件类方法1
class << obj //定义单件类方法2
def ok
puts "aa"
end
end
obj.define_singleton_method :test3 do end //定义单件类方法3
通过obj.singleton_class获得该对象的单件类
同样,每个类对象(如String)也有各自的单件类
class << String //定义String.test
def test
end
end
因此要访问类的所有类方法的话可以使用String.singleton_methods
每个实例对象其实都自带单件类,单件类的父类是该类本身,比如
str = "a"
str.singleton_class.superclass //String类。
而类对象的单件类的父类就比较复杂
class B
class << B
end
end
//B.singleton_class.superclass 为Object类的单件类,即Object.singleton_class,再往上就是BasicObject.singleton_class和Class对象,因此“类静态函数”也是可以继承的