什么class << self在 Ruby 中执行操作?

2010-03-24 03:02:42
问题评论:

没有由 Yehuda Katz 编写本主题有关的非常好文章: yehudakatz.com/2009/11/15/...和 Yugui: yugui.jp/articles/846

另一个超级漂亮的文章︰ integralist.co.uk/posts/eigenclass.html

我能看到这在模块内部,这会让它不同吗?github.com/ruby/rake/blob/master/lib/rake/rake_module.rb

回答:

第一,class << foo的语法打开foo的单独的类 (eigenclass)。这使您可以 specialise 在该特定的对象上调用的方法的行为。

a = 'foo'
class << a
  def inspect
    '"bar"'
  end
end
a.inspect   # => "bar"

a = 'foo'   # new object, new singleton class
a.inspect   # => "foo"

现在,来回答的问题︰class << self开辟self的单独的类,以便可以重新定义方法self当前 (这类或模块的体内是类或模块本身)。通常情况下,这用来定义类/模块 ("静态") 方法︰

class String
  class << self
    def value_of obj
      obj.to_s
    end
  end
end

String.value_of 42   # => "42"

这也可以写成一种简写形式︰

class String
  def self.value_of obj
    obj.to_s
  end
end

或甚至更短︰

def String.value_of obj
  obj.to_s
end

在函数定义中,self指的对象调用该函数时使用。在这种情况下,class << self打开单独的类的对象;它的一个用途是实现廉价的状态机︰

class StateMachineExample
  def process obj
    process_hook obj
  end

private
  def process_state_1 obj
    # ...
    class << self
      alias process_hook process_state_2
    end
  end

  def process_state_2 obj
    # ...
    class << self
      alias process_hook process_state_1
    end
  end

  # Set up initial state
  alias process_hook process_state_1
end

因此,在上例中, StateMachineExample的每个实例都有process_hook化名为process_state_1,但请注意如何在后者,它可以重新定义 (用于self,不会影响其他StateMachineExample实例) 的process_hookprocess_state_2因此,每次在调用方调用process方法 (该调用可重定义process_hook) 的行为更改,具体取决于它的状态。

@Jörg: + 1 以进行编辑 (我希望因此提供了 upvote 的编辑能力; 哦哦)。这确实是更常用的class << self,若要创建类/模块的方法。我将可能展开对该使用class << self,因为这是更习惯使用。

gsub !("eigenclass","单一实例类"),请参阅即将到来的方法redmine.ruby-lang.org/repositories/revision/1?rev=27022

@Marc-Andre︰ 噢,这是一个最新决定 (capitulation? 他似乎非常不情愿在整个线程) 上 Matz 的一部分。仍然,很好,没有达成其势头。

这是真正令人困惑a的指以来a的类 (更改后inspect) 的singleton_class是一个唯一的String类变量。如果它打算改变单一String类,它将影响所有其他String实例。什么是怪仍然是,如果您以后重新打开要重新定义inspect然后a将仍然领取新的更改的String

我仍然愿意为名称 eigenclass,@OldPro (我认为) Matz 还 does。但是,不能请所有人,我猜。

我发现超级简单解释有关class << selfEigenclass和另一种methods在此博客.

在 Ruby 中,有三种可以应用于类的方法︰

  1. 实例方法
  2. 单一实例方法
  3. 类方法

实例方法和类方法都几乎类似于其他编程语言中的 homonymous。

class Foo  
  def an_instance_method  
    puts "I am an instance method"  
  end  
  def self.a_class_method  
    puts "I am a class method"  
  end  
end

foo = Foo.new

def foo.a_singleton_method
  puts "I am a singletone method"
end

访问Eigenclass(其中包括单一实例方法) 的另一种方法是使用下面的语法 (class <<):

foo = Foo.new

class << foo
  def a_singleton_method
    puts "I am a singleton method"
  end
end

现在,您可以定义为self即类Foo本身在此上下文中的单一实例方法︰

class Foo
  class << self
    def a_singleton_and_class_method
      puts "I am a singleton method for self and a class method for Foo"
    end
  end
end

虽然此链接可能回答这些问题,最好包括这里的答案的关键部件,并提供链接供参考。只链接的答案可能会变得无效,如果更改了链接的页面。-从审查

哪类 << thingy 的执行︰

class Hi
  self #=> Hi
  class << self #same as 'class << Hi'
    self #=> #<Class:Hi>
    self == Hi.singleton_class #=> true
  end
end

[它使self == thingy.singleton_class 在它的块的上下文中].


Thingy.singleton_class 是什么?

hi = String.new
def hi.a
end

hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true

从其#singleton_class.instance_methods ,然后从其#class.instance_methods hi对象都继承了其#methods.
这里我们提供给hi单独的类实例方法:a。 它可以通过类 << hi相反。
hi#singleton_class具有所有实例方法具有hi#class和可能是更多 (:a在此处)。

[实例方法的 thingy 的 #class #singleton_class 可以直接应用于 thingy。 当拼音看到 thingy.a,它首先查找︰ 然后在 thingy.singleton_class.instance_methods 和 thingy.class.instance_methods 的方法定义]


顺便说一下,单一实例类的对象的元类= = = = eigenclass.

通常情况下,实例方法是全局方法。这意味着它们将显示在其定义它们的类的所有实例。与此相反,在一个对象上实现单一实例方法。

Ruby 在类中存储方法,必须与类关联的所有方法。在其定义一个单一实例方法的对象不是类 (它是一个类的实例)。如果只类可以存储方法,怎么对象中可存储单一实例方法呢?当创建一个单一实例方法时,Ruby 会自动创建匿名类来存储该方法。这些匿名的类称为元类,也称为单一实例类或 eigenclasses。单一实例方法是反过来,它是与单一实例方法定义在其的对象相关联的元类与关联。

class Zen
end

z1 = Zen.new
z2 = Zen.new

class << z1
  def say_hello
    puts "Hello!"
  end
end

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

在上面的示例中,类 << z1 更改当前的自我,以指向元类的 z1 对象;然后,它定义在元类中的 say_hello 方法。

所有对象都可能都有元类。这意味着类也可以有元类。在上面的示例中,类 << 自我自我修改,使其指向 Zabuton 类的元类。当不明确接收方的情况下定义的方法 (类/对象将在其定义该方法),在当前的范围内,即当前值的隐式地定义它。因此,资料方法是在 Zabuton 类的元类中定义的。上面的示例中是只是另一种方式定义的类方法。IMHO,则最好使用 def self.my_new_clas_method 的语法来定义类的方法,它使代码更易于理解。因此我们弄清发生了什么时,我们遇到过此类包括上面的示例中,是 << 自我的语法。

附加信息可以找到有关 Ruby 类此开机自检.

内容来源于Stack Overflow class << self idiom in Ruby
请输入您的翻译

class << self idiom in Ruby

确认取消