Ruby元编程

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对象,因此“类静态函数”也是可以继承的



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值