什么是Ruby中的self
self
是Ruby中的一个保留关键词,它总是指代当前的对象,类也是对象,但是 指代的对象经常根据情况或上下文而变化。因此,如果你在一个实例中, 指的是该实例。如果你在一个类中, 指的是该类。self
self
self
self指的是上下文
是的,上下文是指你的代码在任何特定时刻所处的位置。
如果你的代码在一个实例方法里面,self
,就是那个类的一个实例。换句话说,self
是一个对象。
让我们尝试一下,输出self
。为了做到这一点,我们需要在对象内部的某个地方添加它。任何方法都可以做到这一点。
def name
puts self
end
name
# => main
这段代码定义并调用了一个.name
方法,该方法打印出了self的值。
self
最初被设置为 ,这是一个对象类的实例,每当Ruby程序被解释时就会自动创建。main
主对象是程序的 "顶层 "命名空间。
无论代码在哪个上下文中发现自己,都必须记住关于self
的一条重要规则:self
在任何时候都是指一个而且只有一个对象。
正如这里所见。
class Person
def name
puts self end
end
Person.new.name
#<Person:0x000056198a868c98>
从这些例子中,我们可以看出,self
的价值会根据你使用它的地方而改变。
我相信你可以通过了解它的目的来更好地理解任何东西。
让我们来看看一些例子。
self 在一个类的定义里面
在一个类的定义中(但不是在一个实例方法中),self
关键字指的是类本身。
这里我们有Person
类,在这个类里面,我们要输出self
的值。
class Person
puts self
end
# => Person (the Person class)
结果是,直接在类定义的上下文中,self
相当于它被定义的父类;在这个例子中,Person
。
在单子方法中,self
关键字也指的是类本身。
class Person
def self.name
puts self
end
end
Person.name
# => Person
为什么我们在方法定义中使用self
?
让我们来看看更常见的使用情况...定义类方法 !
类级方法
我相信你已经在上面的例子中看到了它。这些def self.method_name
方法的定义。
因为我们不必为每个方法定义使用类的名称,如果我们改变了类,我们的代码就更容易改变。
这就是为什么我们做def self.name
,而不是def Person.name
。
另一种更高级的方法是在类实例本身内部定义一个方法。
这被称为eigenclass或singleton类,它使用self
关键字来打开一个新的上下文,其中Class实例被保存在self中。
让我们通过一个例子来看看。
class Person
class << self
def name
puts "Jane"
end
end
end
Person.name
# => "Jane"
实例方法:self
一个实例方法是一个适用于该类所有实例的方法,但不是针对类对象本身。
在Ruby中,定义一个类的实例方法很简单,就是在方法定义中排除self
。Object的前缀;在这个例子中,只用def name
就可以了。
class Person
def name
puts "self inside method is: #{self}"
puts "self.class is: #{self.class}"
return "Jane"
end
end
# Define instance
person = Person.new
person.name
# => self inside method is: #<Person:0x000000010c38be10>
# => self.class is: Person
# => "Jane"
由于这是一个实例方法,在我们创建一个新的Person
类实例之前,我们不能调用它。之后,一旦我们在该实例上调用name方法,我们就能得到完整的输出。
与直接对self的类方法引用不同,对self的实例方法引用实际上指向正在执行的特定实例,因此我们的输出显示了Person
类的一个实例,正如其内存地址所显示的那样。
# => self inside method is: #<Person:0x000000010c38be10>
模块定义中的Self
在模块定义内使用self
与class definition
非常相似。事实上,就 Ruby 而言,对self
的引用并不关心你是在一个类的上下文中,还是在一个模块的上下文中,它对两者的处理基本相同。例如,这里我们将Person
类封闭在Type
模块内,然后在两个上下文中输出 self 的值。
module Type
puts "Self inside Type is: #{self}"
class Person
puts "Self inside Type::Person is: #{self}"
end
end
虽然Ruby对待模块定义调用self
,就像对待类定义一样,在这种情况下代表Type的父级对象,对于子级调用,它认识到这里有一个层次结构,所以我们得到模块和类。
Self inside Type is: Type
Self inside Type::Person is: Type::Person
当不使用实例变量和方法时,self
如何工作?
当一个方法被调用而没有显式的self
,就会使用隐式的self
,也就是关键词self
的值。在下面的例子中,Person#name
方法使用了来自Person#first_name
和Person#last_name
的值,但是没有显式地使用self
,而是依赖于隐式self
的值。
class Person
attr_reader :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name @last_name = last_name
end
def name
"#{first_name} #{last_name}"
end
end
依靠隐含的self
,随着时间的推移可以节省相当多的输入,在Ruby程序员中非常普遍。
摘要
self
是Ruby中的一个关键字,代表当前上下文的默认对象。self
是消息的默认接收者和实例变量的所有者。- 确定
self
的三个规则:1)当当前上下文在任何类/模块/方法定义之外时,self
是main;2)当当前上下文在类/模块定义之内,在方法定义之外时,self
是类/模块;3)当当前上下文在方法定义之内时,self
是方法的接收者,即点(.)之前的对象。