'self' 关键字在此 Class 方法中究竟做了什么?

What is the 'self' keyword doing exactly in this Class method?

  class Restaurant

  attr_accessor :average_rating, :city

  def initialize(city, name)
    @city = city
    @name = name
    @number_of_ratings = 0
    @sum_of_ratings = 0
  end

  def rate(new_rate)
    @number_of_ratings += 1
    @sum_of_ratings += new_rate
    @average_rating = @sum_of_ratings.to_f / @number_of_ratings
  end

  def self.filter_by_city(restaurants, city)
    restaurants.select { |restaurant| restaurant.city == city }
  end
end

以上代码是挑战的一部分,我一直未能通过#filter_by_city 方法的测试。我检查了解决方案,唯一的区别是方法名称之前的 self. 。我试图理解 self 到底做了什么,但没有上下文很难理解。在这个特定的 class 方法中,self 到底在做什么?我知道该方法的主体在做什么,即按城市过滤餐馆,但它是如何 运行 的?

self就是classRestaurantdef self.method 是在 class 本身而不是 class 的实例上实现方法的方式。 Restaurant.filter_by_city(...) 而不是 Restaurant.new.filter_by_city(...).

self 根据上下文在 Ruby 中更改。在方法中,self 是调用该方法的对象。

class Restaurant 块内,在任何方法之外,selfRestaurant 对象,它是一个 Class object。在 Ruby 中一切都是对象。一切。

您也可以通过声明一个块来做到这一点,其中 class 是实例。

class << self
  def filter_by_city(restaurants, city)
    restaurants.select { |restaurant| restaurant.city == city }
  end
end

如果您有很多 class 方法,通常您会使用此语法。

有关更多信息,请参阅 Self in Ruby: A Comprehensive Overview

在 ruby 中定义方法时,您可以选择使用 def <receiver>.<method> 语法而不是简单的 def <method>

显式定义该方法的接收器
object = Object.new

def object.foo
  :foo
end

object.foo #=> foo

接收者必须是单数引用或表达式(但必须用方括号括起来):

a = [Object.new, Object.new]

def (a.first).foo
  :foo
end

def (a[1]).bar
  :bar
end

a[0].foo #=> :foo
a.last.bar #=> :bar
a.first.bar #=> undefined method

定义receiver时,直接在receiver的单例上定义方法class,忽略定义方法的上下文:

class A
  o = Obejct.new
  
  def o.foo
  end
end

A.new.foo #=> undefined method

尽管方法 foo 是在 class 主体中定义的,但由于显式接收者

,它对其实例不可用

self 是返回当前“上下文”的 ruby 关键字。在方法内部,self(通常)是调用的接收者,在模块内部 self returns 那个模块。所以:

module Wrapper
  module SomeModule
    puts self.name
  end
end

将打印 Wrapper::SomeModule.

这意味着:

class A
  def self.foo
  end
end

完全相同:

class A
  def A.foo
  end
end

因此,该方法直接在 A 上定义,并且只能像 A.foo 一样在 class 上直接调用,而不是在其实例上调用。