Chr*_*ung 879
首先,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"
Run Code Online (Sandbox Code Playgroud)
现在,回答这个问题:class << self打开self单例类,以便可以为当前self对象重新定义方法(在类或模块体内部是类或模块本身).通常,这用于定义类/模块("静态")方法:
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Run Code Online (Sandbox Code Playgroud)
这也可以写成速记:
class String
def self.value_of obj
obj.to_s
end
end
Run Code Online (Sandbox Code Playgroud)
甚至更短:
def String.value_of obj
obj.to_s
end
Run Code Online (Sandbox Code Playgroud)
在函数定义内部时,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
Run Code Online (Sandbox Code Playgroud)
因此,在上面的示例中,每个实例StateMachineExample都有process_hook别名process_state_1,但请注意在后者中,它可以重新定义process_hook(self仅用于,不影响其他StateMachineExample实例)process_state_2.因此,每次调用者调用该process方法(调用可重新定义的方法process_hook)时,行为都会根据其所处的状态而变化.
Sam*_*adi 31
我发现了大约一个超级简单的解释class << self,Eigenclass以及不同类型的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
Run Code Online (Sandbox Code Playgroud)
访问class <<(包括单例方法)的另一种方法是使用以下语法(self):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
Run Code Online (Sandbox Code Playgroud)
现在,您可以在此上下文中定义一个单例方法,Foo该方法就是类class << self本身:
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
Run Code Online (Sandbox Code Playgroud)
Bru*_*cca 20
通常,实例方法是全局方法.这意味着它们可以在定义它们的类的所有实例中使用.相反,单个方法是在单个对象上实现的.
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'…
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,类<< z1将当前self改为指向z1对象的元类; 然后,它定义了元类中的say_hello方法.
类也是对象(称为Class的内置类的实例).类方法只不过是与类对象关联的单例方法.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Run Code Online (Sandbox Code Playgroud)
所有对象都可能有元类.这意味着类也可以有元类.在上面的例子中,类<< self修改self,因此它指向Zabuton类的元类.如果定义的方法没有显式接收器(将在其上定义方法的类/对象),则在当前作用域内隐式定义它,即self的当前值.因此,stuff方法是在Zabuton类的元类中定义的.上面的示例只是定义类方法的另一种方法.恕我直言,最好使用def self.my_new_clas_method语法来定义类方法,因为它使代码更容易理解.上面的例子被包含在内,所以我们理解当我们遇到类<< self syntax时发生的事情.
有关Ruby Classes的更多信息可以在这篇文章中找到.
lak*_*are 14
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
Run Code Online (Sandbox Code Playgroud)
[它 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
Run Code Online (Sandbox Code Playgroud)
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]
顺便说一下 - 他们调用object的singleton class == metaclass == eigenclass.
| 归档时间: |
|
| 查看次数: |
135697 次 |
| 最近记录: |