Ruby 类方法与特征类中的方法

发布于 2024-10-03 04:20:17 字数 691 浏览 2 评论 0原文

类方法和该类的特征类(或元类)中的方法只是定义一件事的两种方法吗?

否则的话,有什么区别呢?

class X
  # class method
  def self.a
    "a"
  end

  # eigenclass method
  class << self
    def b
      "b"
    end
  end
end

XaXb 的行为有什么不同吗?

我认识到我可以通过打开特征类来覆盖或别名类方法:

irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"

Are class methods and methods in the eigenclass (or metaclass) of that class just two ways to define one thing?

Otherwise, what are the differences?

class X
  # class method
  def self.a
    "a"
  end

  # eigenclass method
  class << self
    def b
      "b"
    end
  end
end

Do X.a and X.b behave differently in any way?

I recognize that I can overwrite or alias class methods by opening the eigenclass:

irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

杯别 2024-10-10 04:20:17

这两种方法是等效的。 “eigenclass”版本对于使用 attr_* 方法很有帮助,例如:

class Foo
  @instances = []
  class << self;
    attr_reader :instances
  end
  def initialize
    self.class.instances << self
  end
end

2.times{ Foo.new }
p Foo.instances
#=> [#<Foo:0x2a3f020>, #<Foo:0x2a1a5c0>]

您还可以使用 define_singleton_method 在类上创建方法:

Foo.define_singleton_method :bim do "bam!" end

The two methods are equivalent. The 'eigenclass' version is helpful for using the attr_* methods, for example:

class Foo
  @instances = []
  class << self;
    attr_reader :instances
  end
  def initialize
    self.class.instances << self
  end
end

2.times{ Foo.new }
p Foo.instances
#=> [#<Foo:0x2a3f020>, #<Foo:0x2a1a5c0>]

You can also use define_singleton_method to create methods on the class:

Foo.define_singleton_method :bim do "bam!" end
冬天的雪花 2024-10-10 04:20:17

在 Ruby 中,确实不存在类方法之类的东西。由于 Ruby 中的一切都是对象(包括类),因此当您说 def self.class_method 时,您实际上只是在类 Class 的实例上定义了一个单例方法。所以回答你的问题,说

class X
  def self.a
    puts "Hi"
  end

  class << self
    def b
      puts "there"
    end
  end
end

X.a # => Hi
X.b # => there

是说同一件事的两种方式。这两个方法都只是在 Class 对象的实例中定义的单一(eigen、meta、ghost 或任何您想调用的名称)方法,在您的示例中为 X。本主题是元编程的一部分,这是一个有趣的主题,如果您已经使用 Ruby 一段时间,那么您应该查看一下。
Pragmatic Programmers 有一本很棒的关于元编程的书,如果您对元编程感兴趣,您绝对应该看一下话题。

In Ruby there really are no such things as class methods. Since everything is an object in Ruby (including classes), when you say def self.class_method, you are just really defining a singleton method on the instance of the class Class. So to answer your question, saying

class X
  def self.a
    puts "Hi"
  end

  class << self
    def b
      puts "there"
    end
  end
end

X.a # => Hi
X.b # => there

is two ways of saying the same thing. Both these methods are just singeton (eigen, meta, ghost, or whatever you want to call them) methods defined in the instance of your Class object, which in your example was X. This topic is part of metaprogramming, which is a fun topic, that if you have been using Ruby for a while, you should check out.
The Pragmatic Programmers have a great book on metaprogramming that you should definitely take a look at if you interested in the topic.

吻风 2024-10-10 04:20:17

另一位死灵法师在这里挖掘这个老问题...您可能不知道的一件事是将类方法标记为 private (使用 private 关键字而不是 :private_class_method) 与标记特征类方法不同。 :

class Foo
  class << self
    def baz
      puts "Eigenclass public method."
    end

    private
    def qux
      puts "Private method on eigenclass."
    end
  end
  private
  def self.bar
    puts "Private class method."
  end
end

Foo.bar
#=> Private class method.
Foo.baz
#=> Eigenclass public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
#   from (irb)

以下示例将按照上一个示例的方式工作:

class Foo
  class << self
    def baz
      puts "Eigen class public method."
    end

    private
    def qux
      puts "Private method on eigenclass."
    end
  end
  def bar
    puts "Private class method."
  end
  private_class_method :bar
end
Foo.bar
#=> NoMethodError: private method `bar' called for Foo:Class
#     from (irb)
Foo.baz
#=> Eigen class public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
#     from (irb)

Yet another necromancer here to unearth this old question... One thing you might not be aware of is that marking a class method as private (using the private keyword instead of :private_class_method) is different than marking an eigenclass method as such. :

class Foo
  class << self
    def baz
      puts "Eigenclass public method."
    end

    private
    def qux
      puts "Private method on eigenclass."
    end
  end
  private
  def self.bar
    puts "Private class method."
  end
end

Foo.bar
#=> Private class method.
Foo.baz
#=> Eigenclass public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
#   from (irb)

The following example will work how the previous one intends:

class Foo
  class << self
    def baz
      puts "Eigen class public method."
    end

    private
    def qux
      puts "Private method on eigenclass."
    end
  end
  def bar
    puts "Private class method."
  end
  private_class_method :bar
end
Foo.bar
#=> NoMethodError: private method `bar' called for Foo:Class
#     from (irb)
Foo.baz
#=> Eigen class public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
#     from (irb)
星軌x 2024-10-10 04:20:17

Ruby 中使用的大多数实例方法都是全局方法。这意味着它们在定义它们的类的所有实例中都可用。相反,单例方法是在单个对象上实现的。

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

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

class Zen
end

z1 = Zen.new
z2 = Zen.new

def z1.say_hello  # Notice that the method name is prefixed with the object name
  puts "Hello!"
end

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

在上面的示例中,say_hello 方法是在 Zen 类的 z1 实例中定义的,而不是在 z2 实例中定义的。

以下示例显示了定义单例方法的不同方法,但具有相同的结果。

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'…

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

上面的两个例子都说明了单例方法是如何工作的。然而,有一种更简单的方法来定义单例方法:使用名为 Define_singleton_method 的内置方法。

class Zen
end

z1 = Zen.new
z2 = Zen.new

z1.define_singleton_method(:say_hello) { puts "Hello!" }

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

我们之前了解到类也是对象(称为 Class 的内置类的实例)。我们还了解了类方法。 类方法只不过是与类对象关联的单例方法。

再举一个例子:

class Zabuton
  class << self
    def stuff
      puts "Stuffing zabuton…"
    end
  end
end

所有对象都可能具有元类。这意味着类也可以有元类。在上面的例子中,class << self 修改 self,使其指向 Zabuton 类的元类。当一个方法在没有显式接收者(将在其上定义该方法的类/对象)的情况下定义时,它会在当前范围内隐式定义,即 self 的当前值。因此,stuff 方法是在 Zabuton 类的元类中定义的。上面的示例只是定义类方法的另一种方式。

阅读这篇关于 Ruby 类的文章了解更多信息。

Most instance methods used in Ruby are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.

There is an apparent contradiction. Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.

If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.

class Zen
end

z1 = Zen.new
z2 = Zen.new

def z1.say_hello  # Notice that the method name is prefixed with the object name
  puts "Hello!"
end

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

In the above example, the say_hello method was defined within the z1 instance of the Zen class but not the z2 instance.

The following example shows a different way to define a singleton method, with the same result.

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'…

In the above example, class << z1 changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.

Both of the above examples serve to illustrate how singleton methods work. There is, however, an easier way to define a singleton method: using a built-in method called define_singleton_method.

class Zen
end

z1 = Zen.new
z2 = Zen.new

z1.define_singleton_method(:say_hello) { puts "Hello!" }

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

We learned earlier that classes are also objects (instances of the built-in class called Class). We also learned about class methods. Class methods are nothing more than singleton methods associated with a class object.

One more example:

class Zabuton
  class << self
    def stuff
      puts "Stuffing zabuton…"
    end
  end
end

All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method.

Read more at this post about Ruby Classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文