Sql 为什么我能够像调用实例方法一样调用类方法呢?
我在看这个例子:Sql 为什么我能够像调用实例方法一样调用类方法呢?,sql,ruby,metaprogramming,Sql,Ruby,Metaprogramming,我在看这个例子: class SQLObject def self.columns return @columns if @columns columns = DBConnection.execute2(<<-SQL).first SELECT "#{table_name}".* FROM "#{table_name}" LIMIT 0 SQL columns.ma
class SQLObject
def self.columns
return @columns if @columns
columns = DBConnection.execute2(<<-SQL).first
SELECT
"#{table_name}".*
FROM
"#{table_name}"
LIMIT
0
SQL
columns.map!(&:to_sym)
@columns = columns
end
def self.table_name
@table_name ||= self.name.underscore.pluralize
end
def insert
column_symbols = self.class.columns.drop(1)
column_names = column_symbols.map(&:to_s).join(", ")
question_marks = (['?'] * column_symbols.count).join(", ")
DBConnection.execute(<<-SQL, *attribute_values)
INSERT INTO
#{self.class.table_name} (#{column_names})
VALUES
(#{question_marks})
SQL
self.id = DBConnection.last_insert_row_id
end
end
类SQLObject
def self.columns
如果@columns,则返回@columns
columns=DBConnection.execute2(当在抽象类中时,
self
指的是正确的类,而不是对象。这就是为什么您可以访问该方法,而无需显式告诉self
简短回答:self
是Ruby中的隐式接收器。如果您省略它,消息将发送到self
。换句话说,它是never必须在消息发送中说self.foo
,因为foo
总是隐式地与self.foo
相同
详细回答:Ruby中没有“类方法”这样的东西。你所说的“类方法”实际上只是在一个对象上定义的一个单例方法,而这个对象恰好是类的一个实例
实际上,Ruby中也没有单例方法。单例方法实际上只是一个在对象的单例类上定义的常规旧实例方法
[注意:这并不是说你不应该使用这些术语。说“类方法”显然比“类的对象的单例类的实例方法<代码>类代码>”更简单,传达的意图也更好。”。此外,请注意,有些方法,例如。这些术语显然存在于Ruby社区中,但重要的是要理解这些概念在Ruby语言中并不存在。它们是一种交流工具,而不是实际的Ruby概念。]
singleton类是一个与单个对象关联的类。每个对象只有一个singleton类,并且该对象是其singleton类的唯一实例(“singleton instance”,因此得名)
事实上,一个对象的继承层次结构总是从它的单例类开始,也就是说,一个对象的类指针总是指向它的单例类,而单例类的超类指针则指向创建这个对象的类计算继承链时“跳过”单例类。但是,在方法查找过程中始终使用该类
事实上,方法查找实际上非常简单(唯一的例外是,在本文的解释中我将忽略它):
method\u missing
,在这种情况下,引发错误- 定义方法时,您在哪个类(或模块)中定义它
- 发送消息时,您将消息发送到哪个对象
def foo.bar
定义方法时,Ruby将首先计算表达式foo
,然后在结果对象的单例类(被定义对象)上定义方法bar
。如果您不提供foo
,即您只说def bar
,则bar
是在上定义的,这是一个有点棘手的概念。通常,它是最接近词汇的封闭模块定义。如果没有封闭模块定义,即您处于顶层,则默认定义对象为,方法为vi不可能
当您使用foo.bar
发送消息时,Ruby将首先计算表达式foo
,然后将消息bar
发送给结果对象(接收者)。如果您不提供foo
,即如果您只说bar
,那么默认接收者是self
这就引出了下一个问题:
- 什么是自我
self
是导致调用此方法的消息send的接收者。因此,如果您发送消息foo.bar
,则在方法bar
的定义中对self
的任何引用都将在方法的这一次执行期间计算为foo
在模块或类定义主体中,self
是类或方法本身。(这就是为什么在模块或类定义主体中使用def self.bar
定义单例类的单例方法实例方法。)
在一个块或lambda文本中,self
在词汇上被捕获,也就是说,self
在写入块或lambda文本的点上是什么。然而,有两种方法可以改变self
的计算方式,最显著的是,,,…系列方法
如果您在代码中的任何时候都知道这三个问题的答案(我在哪里定义一个方法,方法调用的接收者是什么,self是什么),那么您基本上理解了Ruby最重要的部分
所以,把这一切放在一起:
在使用def self.columns
定义方法时,我们处于类定义主体中,因此self
引用类对象本身(SQLObject
)
语法def foo.bar
在foo
的单例类上定义了一个方法bar
。在这种情况下,您在SQLObject
的单例类上定义了方法columns
。这意味着对象SQLObject
是宇宙中唯一会响应消息c>的对象列
这两者也适用于self.table\u name
的定义
大都会公园内