Взаимодействие attr_accessor и |= operator

#ruby

#ruby

Вопрос:

Я понимаю, что x |= y это в основном означает x = x|y . Оператор | определен для класса Set как вычисляющий объединение двух множеств. Действительно, мы можем видеть:

 require 'set'
r = Set.new(%w(a b)); 
s = Set.new(%w(c d)); 
r |= s; # r => #<Set: {"a", "b", "c", "d"}>
 

Но посмотрите, например, следующее определение класса:

 class Demo; 
  def initialize(s); 
    @x = s.dup; 
  end; 
  attr_accessor :x; 
  def m!(t); 
    x |= t.x; ' <--- HERE TROUBLE!
 end; 
 

завершение

Я использую этот класс следующим образом:

 u = Demo.new(Set.new(%w(a b)))
v = Demo.new(Set.new(%w(c d)))
u.m!(v)
 

Если я сейчас посмотрю на u.x, я увижу, что он по-прежнему содержит множество a,b, а не a,b,c,d. Мне кажется, что это связано с тем, что я использую средство доступа к атрибутам, в частности метод setter . Если бы я написал @x |= t.x , это сработало бы. Может ли быть так, что левая часть x |= t.x использует получатель x , а не установщик x= , тем самым создавая объединение во временном объекте Set?

Кстати, я использую довольно старую версию Ruby (JRuby 1.7.x, примерно соответствующую языковой версии Ruby 1.9.3).

Комментарии:

1. Альтернативно: x.merge(t.x) который добавляет элементы из t.x в x . (без создания нового набора)

Ответ №1:

Причина этого в том, что в

 x = 3
 

x всегда интерпретируется как локальная переменная, прежде чем ruby начнет поиск метода x= . Это означает, что ваш метод преобразуется в:

 def m!(t)
  x = nil # local variable initialization
  x = x | t.x
end;
 

Чтобы решить эту проблему, вам необходимо использовать явный self принудительный вызов метода:

 def m!(t); 
  self.x |= t.x
end
 

Еще одно замечание — пожалуйста, не используйте точки с запятой в ruby. Есть только очень редкие ситуации, в которых они нуждались, но мы обычно их избегаем

Комментарии:

1. Из документации : «При использовании назначения метода у вас всегда должен быть приемник. Если у вас нет получателя, Ruby предполагает, что вы присваиваете локальной переменной »