Ruby中的class<<self习语

class << selfruby中做了什么?

185767 次浏览

首先,class << foo语法打开foo的单例类(特征类)。这允许您专门化该特定对象上调用的方法的行为。

a = 'foo'class << adef inspect'"bar"'endenda.inspect   # => "bar"
a = 'foo'   # new object, new singleton classa.inspect   # => "foo"

现在,回答这个问题:class << self打开了self的单例类,以便可以为当前self对象(在类或模块主体中是类或模块本身)重新定义方法。通常,这用于定义类/模块(“静态”)方法:

class Stringclass << selfdef value_of objobj.to_sendendend
String.value_of 42   # => "42"

这也可以写成速记:

class Stringdef self.value_of objobj.to_sendend

或者更短:

def String.value_of objobj.to_send

当在函数定义中时,self指的是调用函数的对象。在这种情况下,class << self打开该对象的单例类;其中一个用途是实现穷人的状态机:

class StateMachineExampledef process objprocess_hook objend
privatedef process_state_1 obj# ...class << selfalias process_hook process_state_2endend
def process_state_2 obj# ...class << selfalias process_hook process_state_1endend
# Set up initial statealias process_hook process_state_1end

因此,在上面的示例中,StateMachineExample的每个实例都将process_hook别名化为process_state_1,但请注意在后者中,它可以将process_hook(仅用于self,不影响其他StateMachineExample实例)重新定义为process_state_2。因此,每次调用者调用process方法(它调用可重新定义的process_hook)时,行为都会根据它所处的状态而变化。

class<<做什么:

class Hiself #=> Hiclass << self #same as 'class << Hi'self #=> #<Class:Hi>self == Hi.singleton_class #=> trueendend

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


什么是thing.singleton_class?

hi = String.newdef hi.aend
hi.class.instance_methods.include? :a #=> falsehi.singleton_class.instance_methods.include? :a #=> true

hi对象从其#singleton_class.instance_methods继承其#methods,然后从其#class.instance_methods继承。
这里我们给出了hi单例类实例方法:a。它可以用class<代替。
hi#singleton_class拥有hi#class拥有的所有实例方法,可能还有更多(这里是:a)。

事物的实例方法#class#singleton_class当ruby看到Things. a时,它首先在thing.singleton_class.instance中查找:方法定义_methods然后在thing.class.instance_methods]


顺便说一句-他们调用对象的单例类==元类==特征类

我找到了一个关于class << selfEigenclass和不同类型方法的超级简单的解释。

在Ruby中,有三种类型的方法可以应用于一个类:

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

实例方法和类方法几乎与它们在其他编程语言中的同名相似。

class Foodef an_instance_methodputs "I am an instance method"enddef self.a_class_methodputs "I am a class method"endend
foo = Foo.new
def foo.a_singleton_methodputs "I am a singletone method"end

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

foo = Foo.new
class << foodef a_singleton_methodputs "I am a singleton method"endend

现在您可以为self定义一个单例方法,它在上下文中是类Foo本身:

class Fooclass << selfdef a_singleton_and_class_methodputs "I am a singleton method for self and a class method for Foo"endendend

通常,实例方法是全局方法。这意味着它们在定义它们的类的所有实例中都可用。相比之下,单例方法是在单个对象上实现的。

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

如果在单个对象中定义了多个单例方法,则它们都存储在同一个元类中。

class Zenend
z1 = Zen.newz2 = Zen.new
class << z1def say_helloputs "Hello!"endend
z1.say_hello    # Output: Hello!z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

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

类也是对象(称为Class的内置类的实例)。类方法只不过是与类对象关联的单例方法。

class Zabutonclass << selfdef stuffputs "Stuffing zabuton…"endendend

所有的对象都可能有元类,这意味着类也可以有元类。上面的例子中,class<

其他信息可以在关于Ruby类的文章中找到。

A单例法是仅为单个对象定义的方法。

示例:

class SomeClassclass << selfdef testendendend
test_obj = SomeClass.new
def test_obj.test_2end
class << test_objdef test_3endend
puts "Singleton's methods of SomeClass"puts SomeClass.singleton_methodsputs '------------------------------------------'puts "Singleton's methods of test_obj"puts test_obj.singleton_methods

的Singleton方法

测试


辛格尔顿的test_obj方法

test_2

test_3

事实上,如果你为你的Ruby项目编写任何C扩展,实际上只有一种方法来定义模块方法。

rb_define_singleton_method

我知道这个自我业务只是打开了各种其他问题,所以你可以通过搜索每个部分做得更好。

物体第一。

foo = Object.new

我可以为foo创建一个方法吗?

当然可以

def foo.hello'hello'end

我该拿它怎么办?

foo.hello==>"hello"

只是另一个物体。

foo.methods

您将获得所有Object方法以及您的新方法。

def foo.selfselfend
foo.self

只有foo对象。

试着看看如果你从其他对象(如类和模块)中制作foo会发生什么。所有答案中的示例都很好玩,但你必须使用不同的想法或概念来真正理解代码的编写方式。所以现在你有很多术语要看。

辛格尔顿,同学们,模块,自我,对象,和Eigenclass被提出,但Ruby并没有以这种方式命名对象模型。它更像是元类。理查德或__why在这里向您展示了这个想法。http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html如果这让你大吃一惊,那么试着在搜索中查找Ruby对象模型。我知道YouTube上有两个视频是戴夫·托马斯和彼得·库珀。他们也试图解释这个概念。戴夫花了很长时间才明白,所以别担心。我也还在努力。不然我为什么会在这里?谢谢你的提问。还要看看标准库。它有一个单例模块,就像FYI一样。

这是非常好的。https://www.youtube.com/watch?v=i4uiyWA8eFk