Ruby中的self的使用教程

128 阅读5分钟

什么是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

另一种更高级的方法是在类实例本身内部定义一个方法。

这被称为eigenclasssingleton类,它使用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

模块定义内使用selfclass 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_namePerson#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)当当前上下文在任何类/模块/方法定义之外时,selfmain;2)当当前上下文在类/模块定义之内,在方法定义之外时,self类/模块;3)当当前上下文在方法定义之内时,self方法的接收者,即点(.)之前的对象。