Структура с членом и без него

#ruby #struct

#ruby #структура

Вопрос:

Я новичок в Ruby, в настоящее время я собираюсь использовать Struct в классе, чтобы создать временный объект. Однако я сталкиваюсь с вопросом, когда я использую член в структуре, подобной этой:

 class A
  attr_accessor :b
  B = Struct.new(:name, :print_name) do
    def print_name
      p "Hello #{name}"
    end
  end

  def initialize(input_name)
    @b = B.new(input_name)
  end
end

a = A.new('Leo')
a.b.print_name # Hello Leo
 

Но я также получаю тот же результат, когда мои параметры Struct B не включены :print_name .

 B = Struct.new(:name) do
...
end
 

Так в чем же разница? И когда я должен использовать параметр члена, а когда нет?

Спасибо

Ответ №1:

В первом случае вы определяете класс, инициализатор которого принимает два аргумента — name и print_name .

Во втором случае вы определяете класс, инициализатор которого принимает один аргумент — name .

Это не имеет ничего общего с тем фактом, что вы определяете вызываемый метод экземпляра print_name .

Таким образом, экземпляры обоих классов (с print_name аргументом и без него) имеют print_name определенный метод, поэтому оба примера работают одинаково.

Разница будет видна при проверке созданных объектов:

 # first case with two arguments
foo = B.new(:a, :b)
foo.inspect
=> "#<struct B name=:a, print_name=:b>"

# second case with single argument
foo = B.new(:a)
foo.inspect
=> "#<struct B name=:a>"
 

Кроме того, когда вы проверите методы экземпляра класса B для обоих случаев, вы сможете увидеть разницу:

 # first case with two arguments
B.instance_methods false
#=> [:name, :name=, :print_name, :print_name=]

# second case with single argument
B.instance_methods false
#=> [:name, :name=, :print_name]
 

Но я также получаю тот же результат, когда мои параметры Struct B не
включают :print_name

Разница в том, что в первом случае вы можете выполнить следующее:

 a.b.print_name = 'new print name'
a.b.inspect
#=> "#<struct B name='Leo', print_name='new print name'>"
 

Тогда как во втором случае он завершится неудачей:

 a.b.print_name = 'new print name'
#=> NoMethodError: undefined method 'print_name=' for #<struct B name='Leo'>