介绍几种不常见的类定义方法:
?
1. Struct
?
Person=Struct.new(:name,:age,:sex) p=Person.new("liyuchun") puts p
?
?Struct生成一个仅仅包含数据属性的类。但是你可以在这个类的基础上扩展:
?
Person=Struct.new(:name,:age,:sex) class Person def log puts "log here" end end
?
?ok,这样看上去并不是那么的cool,不是嘛。让我们稍微改一下:
?
class Person < Struct.new(:name,:age,:sex) def log puts "log here" end end
?
?it seems better. "<" 只要求后面跟着任何返回一个class object的表达式即可。
?
2. Class.new
我们是怎么定义一个类的?
?
class A end a = A.new
追根溯源,A是一个Class类的对象,而a是A类的对象。既然A通过new方法可以生成a,那么是否可以Class也可以通过new方法生成A呢?of course.
?
?
A = Class.new do def self.log puts "log here" end def log puts "log there" end end a=A.new A.log a.log
?
By default,新生成的类会继承自Object。But,if I want to change? Still easy :?
? A = Class.new(String) do ... end
此时,A就是继承自String类。
?
3. instance_eval和class_eval
何以解忧?唯有看代码。
?
class MyClass end MyClass.class_eval do def instance_method puts "In an instance method" end end obj = MyClass.new obj.instance_method
?然后
?
class MyClass end MyClass.instance_eval do def class_method puts "In a class method" end end MyClass.class_method
class_eval生成的是实例方法,instance_eval生成的是类方法,何须多言啊,呵呵。
also,
?
animal = "cat" "dog".instance_exec(animal) do |other| puts "#{other} and #{self}" end
Ruby 1.9 引进了一些变种. Object#instance_exec, Module#class_exec和Module#module_exec使用instance_exec,你可以将参数传入block。
?
ok,我们可以利用class_eval实现attr_accessor的功能了:
?
module Mod def attr_reader1(*syms) syms.each do |sym| class_eval %{ def #{sym} @#{sym} end} end end end class A extend Mod attr_reader1 :name def initialize @name = "jinbin" end end a=A.new puts a.name
原来这里用的是include Mod,是不正确的。但是恰巧命名的函数为attr_reader,结果程序竟然也能运行通过,呵呵。ATTENTION!
?
这里使用了class_eval函数,出于对比,也用instance_eval来写了一个:
module Mod def attr_reader(*syms) syms.each do |sym| instance_eval %{ def #{sym} @#{sym} end} end end end class A extend Mod attr_reader :name @name = "jinbin" def initialize end end puts A.name由于class_eval生成的是实例方法,instance_eval生成的是类方法,所以调用上有所区别,在代码中都有体现。此处可以细细深究一下,注意self的值。
?