如果self指向ruby中的klassobject,为什么在ActiveRecord中将其用作赋值?
If self points to the klass object in ruby, why is it used as assignment in ActiveRecord?
注意:这是我能想到的最好的标题,它不会让这个问题看起来像一个骗局。如果没有抓住问题的要点,请随时编辑
所以我一直在阅读 Advanced Rails 并且我有一个问题没有被这些帖子完全回答:
- When to use `self.foo` instead of `foo` in Ruby methods
- In Ruby. How do I refer to the class from within class << self definition?
- Why use "self" to access ActiveRecord/Rails model properties?
在我的理解中,在class定义中,self
指的是指针klass
引用的object,所以对于[=34]的例子=]:
class A
class << self
def to.s
"Woot"
end
end
end
与:
完全相同
class << A
def to.s
"Woot"
end
end
这是因为当您打开 class 时,ruby 正在创建 Class:A (virtual)
class 并分配 A
的 klass
指向它的指针。据我了解,这意味着在此 class 定义的上下文中 self == A
我的问题是(假设我在上面描述的理解是准确的)为什么在 ActiveRecord::Base subclass in Rails 中使用 self
似乎只是 instance
而不是 class
本身的消歧?
例如,如果我有一个 class: A < ActiveRecord::Base
和属性 name
,我不能在 class 定义之外调用 A.name = "blah"
。但是,我可以在 class 定义中的赋值中使用(并且实际上必须使用)self,如下所示:self.name = "blah"
。
如果在 Ruby 中使用 self
指的是 Class
object 而不是 instance
,为什么这在 ActiveRecord 中起作用以及如何Rails 有区别吗?
一切都是方法
你对对象所做的任何事情都是一种方法。当你有这样的 class 时:
class A
attr_accessor :foo
end
obj = A.new
obj.foo = 3
obj.foo #=> 3
感觉有点奇怪,你这里没有赋值。 obj.foo = 3
只是 obj.send(:foo=, 3)
的合成糖,所以实际上它执行了 foo=
方法。 obj.foo
也是一种方法,它只是 returns 一个值。这是因为所有实例变量都是私有的,除了在方法内部没有其他方式可以与它们交互。 attr_accessor :foo
只是一个快捷方式:
def foo=(value)
@foo = value
end
def foo
@foo
end
现在,当 ruby 看到任何像 foo
这样的标识符时,它需要找出它是什么。首先,它假设它是一个局部变量,如果不是,它会尝试将它作为当前 self
上的方法执行(见下文)。这意味着:
class A
attr_accessor :foo
def bar
foo = 'bar'
end
end
a = A.new
a.bar #=> 'bar'
a.foo #=> nil
发生了什么事?解释器首先使用 foo
作为实例变量,它没有被定义。但是它旁边有一个赋值,所以它定义了一个新的实例变量并进行了赋值。如果我们想使用我们的 setter 我们需要告诉解释器它不是一个实例变量:
class A
attr_accessor :foo
def bar
self.foo = 'bar'
end
end
a = A.new
a.bar #=> 'bar'
a.foo #=> 'bar'
我撒谎了。万物皆对象
关于自己
ruby 中的 self
与 javascript 中的 this
非常相似 - 它在不同的上下文中表示不同的意思,并且可以随时轻松更改(显然,不推荐)。
首先你要知道在Ruby中每个class都是一个对象,即它是classClass的一个实例。当你这样做时
class A
它(几乎,下面的方法使用块并可以访问外部范围)等同于:
A = Class.new
self
在 class 的上下文中始终是 class 本身。
class A
self #=> A
def self.bar #=> this is class method
self #=> A
end
def foo #=> this is instance method
# We are no longer in context of class, but in context of the instance, hence
self #=> instance of A
end
end
现在,您可以为任何可变对象定义单例 class。这是一个奇怪的概念——它是原始 class 的一个额外子 class,只有一个实例。由于所有方法都来自 class,这允许您在方法的特定实例上定义额外的方法而不影响其他对象。在大多数情况下,实例 class 是不需要的,它是在您第一次访问它时创建的。有几种打开方式:
object.singleton_class do
self #=> instance class
end
class << object
self #=> instance class
end
您在实例 class 中定义的任何方法只能在该特定实例上访问,因此:
class A
self #=> A
class << A
# we are now in the instance class of A (which is an instance of Class class)
def foo
# So this is an instance method, however our instance is a class A
self #=> A
end
end
注意:这是我能想到的最好的标题,它不会让这个问题看起来像一个骗局。如果没有抓住问题的要点,请随时编辑
所以我一直在阅读 Advanced Rails 并且我有一个问题没有被这些帖子完全回答:
- When to use `self.foo` instead of `foo` in Ruby methods
- In Ruby. How do I refer to the class from within class << self definition?
- Why use "self" to access ActiveRecord/Rails model properties?
在我的理解中,在class定义中,self
指的是指针klass
引用的object,所以对于[=34]的例子=]:
class A
class << self
def to.s
"Woot"
end
end
end
与:
完全相同class << A
def to.s
"Woot"
end
end
这是因为当您打开 class 时,ruby 正在创建 Class:A (virtual)
class 并分配 A
的 klass
指向它的指针。据我了解,这意味着在此 class 定义的上下文中 self == A
我的问题是(假设我在上面描述的理解是准确的)为什么在 ActiveRecord::Base subclass in Rails 中使用 self
似乎只是 instance
而不是 class
本身的消歧?
例如,如果我有一个 class: A < ActiveRecord::Base
和属性 name
,我不能在 class 定义之外调用 A.name = "blah"
。但是,我可以在 class 定义中的赋值中使用(并且实际上必须使用)self,如下所示:self.name = "blah"
。
如果在 Ruby 中使用 self
指的是 Class
object 而不是 instance
,为什么这在 ActiveRecord 中起作用以及如何Rails 有区别吗?
一切都是方法
你对对象所做的任何事情都是一种方法。当你有这样的 class 时:
class A
attr_accessor :foo
end
obj = A.new
obj.foo = 3
obj.foo #=> 3
感觉有点奇怪,你这里没有赋值。 obj.foo = 3
只是 obj.send(:foo=, 3)
的合成糖,所以实际上它执行了 foo=
方法。 obj.foo
也是一种方法,它只是 returns 一个值。这是因为所有实例变量都是私有的,除了在方法内部没有其他方式可以与它们交互。 attr_accessor :foo
只是一个快捷方式:
def foo=(value)
@foo = value
end
def foo
@foo
end
现在,当 ruby 看到任何像 foo
这样的标识符时,它需要找出它是什么。首先,它假设它是一个局部变量,如果不是,它会尝试将它作为当前 self
上的方法执行(见下文)。这意味着:
class A
attr_accessor :foo
def bar
foo = 'bar'
end
end
a = A.new
a.bar #=> 'bar'
a.foo #=> nil
发生了什么事?解释器首先使用 foo
作为实例变量,它没有被定义。但是它旁边有一个赋值,所以它定义了一个新的实例变量并进行了赋值。如果我们想使用我们的 setter 我们需要告诉解释器它不是一个实例变量:
class A
attr_accessor :foo
def bar
self.foo = 'bar'
end
end
a = A.new
a.bar #=> 'bar'
a.foo #=> 'bar'
我撒谎了。万物皆对象
关于自己
ruby 中的self
与 javascript 中的 this
非常相似 - 它在不同的上下文中表示不同的意思,并且可以随时轻松更改(显然,不推荐)。
首先你要知道在Ruby中每个class都是一个对象,即它是classClass的一个实例。当你这样做时
class A
它(几乎,下面的方法使用块并可以访问外部范围)等同于:
A = Class.new
self
在 class 的上下文中始终是 class 本身。
class A
self #=> A
def self.bar #=> this is class method
self #=> A
end
def foo #=> this is instance method
# We are no longer in context of class, but in context of the instance, hence
self #=> instance of A
end
end
现在,您可以为任何可变对象定义单例 class。这是一个奇怪的概念——它是原始 class 的一个额外子 class,只有一个实例。由于所有方法都来自 class,这允许您在方法的特定实例上定义额外的方法而不影响其他对象。在大多数情况下,实例 class 是不需要的,它是在您第一次访问它时创建的。有几种打开方式:
object.singleton_class do
self #=> instance class
end
class << object
self #=> instance class
end
您在实例 class 中定义的任何方法只能在该特定实例上访问,因此:
class A
self #=> A
class << A
# we are now in the instance class of A (which is an instance of Class class)
def foo
# So this is an instance method, however our instance is a class A
self #=> A
end
end