class << self
在Ruby中做什么?
class << self
在Ruby中做什么?
Answers:
首先,class << foo
语法打开了foo
单例类(eigenclass)。这使您可以专门化在该特定对象上调用的方法的行为。
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
的singleton类,以便可以为当前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
,但请注意,在后者中,它如何可以重新定义process_hook
(self
仅用于(不影响其他StateMachineExample
实例))process_state_2
。因此,每次调用者调用该process
方法(调用redefinable process_hook
)时,行为都会根据其所处的状态而变化。
class << self
创建类/模块方法的更常见用法。我可能会扩展对的使用class << self
,因为这是更惯用的用法。
a
的singleton_class
自a
的类(转换后inspect
)是一个独特的变种String
类。如果要更改单例String
类,它将影响所有其他String
实例。仍然很奇怪的是,如果您以后重新打开String
以重新定义,inspect
那么a
仍然会选择新的更改。
class << self
等于的值self
等于单例类?
我发现了大约一个超级简单的解释class << self
,Eigenclass
以及不同类型的方法。
在Ruby中,可以将三种类型的方法应用于类:
实例方法和类方法几乎与其他编程语言中的同名方法相似。
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
foo.singleton_class.instance_methods(false)
用来检查。
通常,实例方法是全局方法。这意味着它们在定义它们的类的所有实例中都可用。相反,单例方法是在单个对象上实现的。
Ruby将方法存储在类中,并且所有方法都必须与一个类相关联。定义单例方法的对象不是类(它是类的实例)。如果只有类可以存储方法,那么对象如何存储单例方法?创建单例方法时,Ruby会自动创建一个匿名类来存储该方法。这些匿名类称为元类,也称为单例类或本征类。单例方法与元类相关联,而该元类又与定义了单例方法的对象相关联。
如果在单个对象中定义了多个单例方法,则它们都将存储在同一元类中。
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将当前的self更改为指向z1对象的元类;然后,它在元类中定义say_hello方法。
类也是对象(称为Class的内置类的实例)。类方法只不过是与类对象关联的单例方法。
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
所有对象都可以具有元类。这意味着类也可以具有元类。在上面的示例中,类<< self修改了self,因此它指向Zabuton类的元类。如果在没有显式接收方的情况下定义方法(将在其上定义方法的类/对象),则会在当前范围(即self的当前值)内隐式定义该方法。因此,填充方法在Zabuton类的元类中定义。上面的示例只是定义类方法的另一种方法。恕我直言,最好使用def self.my_new_clas_method语法定义类方法,因为它使代码更易于理解。包含了上面的示例,因此我们了解了遇到类<< self语法时发生的情况。
在这篇关于Ruby Classes的文章中可以找到更多信息。
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[它 self == thing.singleton_class
在其块的上下文中进行]。
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
对象继承其#methods
从它的#singleton_class.instance_methods
,然后从它的#class.instance_methods
。
在这里,我们给hi
的单独的类实例的方法:a
。可以用类<< hi代替。
hi
的#singleton_class
拥有所有实例方法hi
的#class
有,可能还有一些更多(:a
在这里)。
事情的的[实例方法 #class
,并 #singleton_class
可以直接应用到的事情。当ruby看到thing.a时,它首先在thing.singleton_class.instance_methods中寻找:方法定义,然后在thing.class.instance_methods中寻找]
顺便说一句-他们称呼对象的单例类 == 元类 ==本征类。
?singleton方法是仅针对单个对象定义的方法。
例:
class SomeClass
class << self
def test
end
end
end
test_obj = SomeClass.new
def test_obj.test_2
end
class << test_obj
def test_3
end
end
puts "Singleton's methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton's methods of test_obj"
puts test_obj.singleton_methods
SomeClass的Singleton方法
测试
Singleton的test_obj方法
测试_2
test_3
实际上,如果您为Ruby项目编写任何C扩展,则实际上只有一种定义Module方法的方法。
rb_define_singleton_method
我知道这种自我交易只会带来其他各种问题,因此您可以通过搜索每个部分来做得更好。
首先对象。
foo = Object.new
我可以为foo创建方法吗?
当然
def foo.hello
'hello'
end
我该怎么办?
foo.hello
==>"hello"
只是另一个对象。
foo.methods
您将获得所有Object方法以及新方法。
def foo.self
self
end
foo.self
只是foo对象。
尝试看看如果从其他对象(如类和模块)中创建foo会发生什么。所有答案中的示例都很有趣,但是您必须使用不同的想法或概念才能真正理解代码编写方式所发生的事情。因此,现在您有很多术语需要研究。
出现了Singleton,Class,Module,self,Object和Eigenclass,但是Ruby并没有这样命名对象模型。它更像元类。理查德(Richard)或__为什么在这里展示您的想法。 http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html 如果让您大吃一惊,请尝试在搜索中查找Ruby Object Model。我在YouTube上知道的两个视频是Dave Thomas和Peter Cooper。他们也试图解释这个概念。戴夫花了很长时间才得到它,所以不用担心。我也还在努力。我为什么还要在这里?感谢您的提问。还要看一下标准库。与FYI一样,它具有一个Singleton模块。