以下是来自Why's Poignant Guide to Ruby Chapter 6的Ruby代码片段,他试图在Ruby中演示元编程:
# Get a metaclass for this class
def self.metaclass; class << self; self; end; end
我对Ruby并不熟悉,但这是扩展形式的样子吗?
def self.metaclass
def self.self
end
end
至少我就是这么理解的。但是,它仍然无法理解这段代码的作用。 目的是什么?
在代码中,为什么要添加:
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |val|
@traits ||= {}
@traits[a] = val
end
end
end
如果我理解正确,这段代码会给@traits添加一个具有给定名称和值的新值。 这是正确的吗?
感谢您的帮助,这里有给我带来麻烦的完整源代码,对于任何想要看到它的人来说:
# The guts of life force within Dwemthy's Array
class Creature
# Get a metaclass for this class
def self.metaclass; class << self; self; end; end
# Advanced metaprogramming code for nice, clean traits
def self.traits( *arr )
return @traits if arr.empty?
# 1. Set up accessors for each variable
attr_accessor *arr
# 2. Add a new class method to for each trait.
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |val|
@traits ||= {}
@traits[a] = val
end
end
end
# 3. For each monster, the `initialize' method
# should use the default number for each trait.
class_eval do
define_method( :initialize ) do
self.class.traits.each do |k,v|
instance_variable_set("@#{k}", v)
end
end
end
end
# Creature attributes are read-only
traits :life, :strength, :charisma, :weapon
end
并且在使用中:
class Dragon < Creature
life( 1340 ) # tough scales
strength( 451 ) # bristling veins
charisma( 1020 ) # toothy smile
weapon( 939 ) # fire breath
end
答案 0 :(得分:5)
class Foo
def self.bar # Create a method invoked by Foo.bar instead of Foo.new.bar
42 # the return value of this method (value of last expression)
end
end
class Foo
def self.jim # Another method on the class itself
class << self # Change the 'self' to be the metaclass of the current object
self # Evaluate the current 'self' as the 'return value' of
end # class<<self…end; and since this is the last expression in
end # the method, its value is the return value for the method
end
简而言之:您所看到的内容在metaclass
类本身定义了一个名为Creature
的方法(不适用于实例)。运行此方法时,它会找到Creature
的元类并返回该值。
Read around the 'net表示对象的“元类”。
答案 1 :(得分:2)
在扩展形式中,它看起来完全相同:
def self.metaclass
class << self
self
end
end
注意它只是返回self
,因为它是在元类的上下文中进行评估的,这实际上是class << self
所做的,self
是元类。
通过引入define_singleton_method之类的内容,您需要直接访问元类的情况变得非常小。
这都是very complicated,似乎是“一切都是对象”设计原则的结果。