1.使用 Module#class_eval 打开一个类
- class_eval 会同时修改 self 和当前类, 而instance_eval 仅仅会修改 self
-
class_eval 与 class 关键字相比, 使用的是扁平作用域
def add_method_to(a_class) a_class.class_eval do def m; 'Hello!'; end end end add_method_to String "abc".m # => "Hello!"
2.类实例变量, 类的实例对象的实例变量, 类变量
class MyClass
@my_var = 1
end
class MyClass
@my_var = 1
def self.read; @my_var; end
def write; @my_var = 2; end
def read; @my_var; end
end
obj = MyClass.new
obj.write
obj.read # => 2
MyClass.read # => 1
# 类变量
class C
@@v = 1
end
class D < C
def my_method; @@v; end
end
D.new.my_method # => 1
@@v = 1
class MyClass
@@v = 2
end
# 访问外部类变量
@@v # => 2
3.通过 eigenclass 定义类属性, 类方法
class MyClass
class << self
attr_accessor :c
def hello
"Hello"
end
end
end
MyClass.c = 'It works!'
MyClass.c # => "It works!"
MyClass.hello # => "Hello"
4.通过 Object#extend 和 include 来扩展类
module MyModule
def my_method; 'hello'; end
end
obj = Object.new
obj.extend MyModule
obj.my_method # => "hello"
class MyClass
extend MyModule
end
MyClass.my_method # => "hello"
module MyModule
def my_method; 'hello'; end
end
class MyClass
class << self
include MyModule
end
end
MyClass.my_method # => "hello"
5.alias 环绕别名
class String
# 先定义别名
alias :real_length :length
# 重定义length
def length
real_length > 5 ? 'long' : 'short'
end
end
"War and Peace".length # => "long"
"War and Peace".real_length # => 13
class Fixnum
alias :old_plus :+
def +(value)
self.old_plus(value).old_plus(1)
end
end
1 + 1 # => 3
1 - 1 # => 0
6.动态转发实现 deprecate 废弃方法
class Book
def title # ...
end
def subtitle # ...
end
def lend_to(user)
puts "Lending to #{user}"
# ...
end
def self.deprecate(old_method, new_method)
define_method(old_method) do |*args, &block|
warn "Warning: #{old_method}() is deprecated. Use #{new_method}()."
send(new_method, *args, &block)
end
end
deprecate :GetTitle, :title
deprecate :LEND_TO_USER, :lend_to
deprecate :title2, :subtitle
end
b = Book.new
b.LEND_TO_USER("Bill")
# >> Warning: LEND_TO_USER() is deprecated. Use lend_to().
# >> Lending to Bill