Ruby 中的属性访问器

Nurudeen Ibrahim 2023年1月30日
  1. 在 Ruby 中使用简单类创建实例变量 full_name
  2. 在 Ruby 中使用 attr_reader 来读取多个实例变量
  3. 在 Ruby 中使用 attr_writer 编写多个实例变量
  4. 在 Ruby 中将 attr_readerattr_writer 组合成 attr_accessor
Ruby 中的属性访问器

attr_accessor 是 Ruby OOP 设计中 attr_readerattr_writer 的快捷方式。

因此,要了解 attr_accessor,你必须首先了解 attr_readerattr_writer 是如何工作的。为了说明这些是如何工作的,我们将创建一个简单的类。

在 Ruby 中使用简单类创建实例变量 full_name

class Employee
  def initialize(last_name, first_name)
    @full_name = "#{last_name} #{first_name}"
  end
end

employee1 = Employee.new("John", "Doe")
puts employee1.full_name

输出:

undefined method 'full_name' for #<Employee:0x0000558c7cbc9400 @full_name="John Doe"> (NoMethodError)

上面的简单 Employee 类有一个构造函数,它接受员工的姓氏和名字,并使用它来创建实例变量 full_name

如果我们创建这个类的一个实例并读取 full_name,我们会收到 NoMethodError 错误,如上面的输出所示。我们将需要创建另一个返回实例变量的方法。

class Employee
  def initialize(last_name, first_name)
    @full_name = "#{last_name} #{first_name}"
  end

  def full_name
    @full_name
  end
end

employee1 = Employee.new("John", "Doe")
puts employee1.full_name

输出:

John Doe

在 Ruby 中使用 attr_reader 来读取多个实例变量

这是否意味着如果我们有多个需要读取的实例变量,我们将不得不为每个变量创建一个方法?

那会使我们的课不必要地长。因此,Ruby 为我们提供了 attr_reader 来实现这一点。

class Employee
  attr_reader :full_name

  def initialize(last_name, first_name)
    @full_name = "#{last_name} #{first_name}"
  end
end

employee1 = Employee.new("John", "Doe")
puts employee1.full_name

输出:

John Doe

正如你在上面的代码中看到的,我们的输出与前面的代码相同。attr_reader :full_name 的添加在底层添加了 full_name 方法,允许我们编写一个简洁的类。

假设我们还需要重置实例变量。我们可能会尝试这样的事情:

class Employee
  attr_reader :full_name

  def initialize(last_name, first_name)
    @full_name = "#{last_name} #{first_name}"
  end
end

employee1 = Employee.new("John", "Doe")
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = "Nicolas Daniel"

输出:

undefined method 'full_name=' for #<Employee:0x000055bc12240940 @full_name="John Doe"> (NoMethodError)

一种方法是定义一个重置实例变量的 full_name= setter 方法。

class Employee
  attr_reader :full_name

  def initialize(last_name, first_name)
    @full_name = "#{last_name} #{first_name}"
  end

  def full_name=(name)
    @full_name = name
  end
end

employee1 = Employee.new("John", "Doe")
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = "Nicolas Daniel"
puts employee1.full_name

输出:

Nicolas Daniel

在 Ruby 中使用 attr_writer 编写多个实例变量

Ruby 并没有像我们在这里所做的那样定义一个单独的 setter 方法,而是为我们提供了可以帮助我们的 attr_writer

class Employee
  attr_reader :full_name
  attr_writer :full_name

  def initialize(last_name, first_name)
    @full_name = "#{last_name} #{first_name}"
  end
end

employee1 = Employee.new("John", "Doe")
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = "Nicolas Daniel"
puts employee1.full_name

输出:

Nicolas Daniel

正如我们在上面的输出中所看到的,即使我们删除了之前定义的 setter 方法,添加 attr_writer 也得到了相同的结果。

在 Ruby 中将 attr_readerattr_writer 组合成 attr_accessor

我们的最终代码比为每个实例变量定义 getter 和 setter 方法要好得多,但是 Ruby 仍然允许我们通过将 attr_readerattr_writer 组合到 attr_accessor 中更进一步。

class Employee
  attr_accessor :full_name

  def initialize(last_name, first_name)
    @full_name = "#{last_name} #{first_name}"
  end
end

employee1 = Employee.new("John", "Doe")
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = "Nicolas Daniel"
puts employee1.full_name

输出:

Nicolas Daniel

正如我们在上面看到的,使用 attr_accessor,我们会自动为实例变量创建一个 getter 和一个 setter。