为什么我要使用class << Class
语法向类添加任何内容?
class Fun
def much_fun
# some code here
end
end
class << Fun # the difference is here!
def much_more_fun
# some code here
end
end
而不是使用猴子补丁/鸭子打孔方法:
class Fun
def much_fun
# some code here
end
end
class Fun # the difference is here!
def much_more_fun
# some code here
end
end
在阅读Why's Poignant Guide to Ruby时,我遇到了:
为什么要定义一个班级LotteryDraw
:
class LotteryDraw
# some code here
def LotteryDraw.buy( customer, *tickets )
# some code here as well
end
end
并在一段时间后向LotteryDraw
类添加了一个方法:
class << LotteryDraw
def play
# some code here
end
end
说:
当你看到
class << obj
时,相信你的内心,我会直接添加obj
的定义。
这种语法的目的是什么?为什么为什么决定这样做而不是使用猴子补丁方法?
以下是一些相关问题和网站:
class << Class
语法。答案 0 :(得分:4)
需要更多解释。在ruby中,几乎每个对象都可以创建一个称为实例类的奇怪的东西。这个东西就像一个普通的类,主要区别在于它只有一个实例,并且该实例是在该类之前创建的。
简而言之,有了A级,你可以这样做:
a = A.new
b = A.new
a
和b
现在都是A类的实例,并且可以访问此类中定义的所有实例方法。现在让我们说,我们想要添加一个额外的方法,它只能由a
访问,而不能由b
访问(这在某些情况下可能很有用,但如果可能的话,请避免使用它)。所有方法都在类中定义,因此我们似乎需要将它添加到类A中,但这样它也可以由b
访问。在这种情况下,我们需要为a
对象创建一个实例类。为此,我们使用class << <object>
语法:
class << a
def foo
end
end
a.foo #=> nil
b.foo #=> undefined method
简而言之,class << <object>
打开给定对象的实例类,允许为给定实例定义其他实例方法,这些方法在任何其他对象上都不可用。
现在,有了这样说:在Ruby中,类是类Class的最佳实例。这样:
class A
end
几乎相当于(差异在这里不重要)
A = Class.new
因此,如果类是对象,则可以创建实例类。
class << A
def foo
end
end
A.foo #=> nil
Class.new.foo #=> undefined method
它通常用于向给定的类添加所谓的类方法,但关键是实际上是在类的实例类上创建实例方法。
答案 1 :(得分:3)
第一个定义了一个实例方法:
class Fun
def much_fun
puts 'hello'
end
end
fun = Fun.new
fun.much_fun
#=> "hello"
Fun.hello
#=> NoMethodError: undefined method `hello' for Fun:Class
<<
版本定义了一个类方法:
class Fun
class << self # or Fun
def much_more_fun
puts 'hello'
end
end
end
fun = Fun.new
fun.much_more_fun
#=> NoMethodError: undefined method `much_more_fun' for #<Fun:0x007fafdb9ff0a0>
Fun.much_more_fun
#=> "hello"
请注意,第二个版本也可以写为:
class Fun
def self.much_more_fun
puts 'hello'
end
end
答案 2 :(得分:1)
我认为class << Class
用于类方法而不是实例方法:
class Foo
class << Foo
def bar
end
end
end
Foo.bar
#Bar是类方法。
Ruby有各种方法来定义类方法,例如:
class Foo
class << self
def bar
p 'hi'
end
end
def Foo.age
p '24'
end
def self.gender
p 'male'
end
end
Foo.instance_eval do
def name
p 'hello'
end
end
Foo.define_singleton_method(:status) do
p 'single'
end
Foo.bar #> 'hi'
Foo.name #> 'hello'
Foo.age #> '24'
Foo.gender #>male
Foo.status #>single