“class<< Class”(尖括号)语法的目的是什么?

时间:2015-10-31 15:08:25

标签: ruby class syntax

为什么我要使用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的定义。

这种语法的目的是什么?为什么为什么决定这样做而不是使用猴子补丁方法?

以下是一些相关问题和网站:

3 个答案:

答案 0 :(得分:4)

需要更多解释。在ruby中,几乎每个对象都可以创建一个称为实例类的奇怪的东西。这个东西就像一个普通的类,主要区别在于它只有一个实例,并且该实例是在该类之前创建的。

简而言之,有了A级,你可以这样做:

a = A.new
b = A.new

ab现在都是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