'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
就是classRestaurant
。 def self.method
是在 class 本身而不是 class 的实例上实现方法的方式。 Restaurant.filter_by_city(...)
而不是 Restaurant.new.filter_by_city(...)
.
self
根据上下文在 Ruby 中更改。在方法中,self
是调用该方法的对象。
在 class Restaurant
块内,在任何方法之外,self
是 Restaurant
对象,它是一个 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 上直接调用,而不是在其实例上调用。
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
就是classRestaurant
。 def self.method
是在 class 本身而不是 class 的实例上实现方法的方式。 Restaurant.filter_by_city(...)
而不是 Restaurant.new.filter_by_city(...)
.
self
根据上下文在 Ruby 中更改。在方法中,self
是调用该方法的对象。
在 class Restaurant
块内,在任何方法之外,self
是 Restaurant
对象,它是一个 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 上直接调用,而不是在其实例上调用。