Tricky ruby ​​class init ---- почему один и тот же класс инициализирует вывод по-разному? - PullRequest
3 голосов
/ 04 марта 2012

посмотрите этот класс:

class Test
  def initialize a, b, c
    @a = a, @b = b, @c = c
  end
  end

class AnotherTest
  def initialize a, b, c
    @a = a
    @b = b
    @c = c
  end
end

array = []

array.push Test.new "a1" ,"b1", "c1"
array.push AnotherTest.new "a2" ,"b2", "c2"

p array

Я думаю, что это должно быть то же самое, но не:

<Test:0x000000022aba78 @b="b1", @c="c1", @a=["a1", "b1", "c1"]>
<AnotherTest:0x000000022ab9b0 @a="a2", @b="b2", @c="c2">]

Кто-нибудь, кто может дать мне объяснение?

Ответы [ 4 ]

4 голосов
/ 04 марта 2012

Если вы попробуете в irb это выражение:

a = "something" #=> "something"

Как видите, операция присваивания возвращает результат, потому что в ruby ​​каждое выражение должно что-то возвращать. Итак, это выражение:

@b = b #=> b

вернет значение @b. Тогда в этом выражении

@a = a, @b = b, @c = c

, где @b = b и @c = c будут оцениваться до b и c

Итак, наконец, у нас будет это выражение:

@a = a, b, c

И, как вы знаете, это еще одна форма для инициализации массива

@a = [a, b, c]

Этот код будет работать так же, как ваш:

class Test
  def initialize a, b, c
    @a = a, b, c
    @b = b
    @c = c
  end
end

Дополнение: Порядок оценки является значительным. Если вы попробуете это выражение:

@a = a, (@b = b, @c = c)

Во-первых, он будет оценивать все в скобках:

@b = b, @c = c #=> @b = [b,c] and @c = c

Итак, мы получим это

@a = [a,[b,c]]
@b = [b,c]
@c = c
3 голосов
/ 04 марта 2012

Параллельное присваивание выглядит так:

@a, @b, @c = a, b, c

Не только в ruby, это выглядит так на каждом языке, который выполняет параллельное назначение.

2 голосов
/ 04 марта 2012

@a инициализируется массивом значений.Вы можете написать a = 1, 2, 3 и a будет присвоен список [1, 2, 3].Следовательно, @a в вашем примере назначается в виде списка из трех значений 'a1', 'b1' и 'c1'.

..

То, что вы, возможно, хотели, просто:

class Test       
  def initialize a, b, c       
    @a = a; @b = b; @c = c       
  end       
end   
1 голос
/ 04 марта 2012

Запятая в операторе присваивания обрабатывается специально в Ruby.Таким образом, приведенный выше результат.

 @a = a, @b = b, @c = c

В вышеприведенном выражении Ruby видит first = как часть оператора присваивания.Ruby видит значения в правой части равенства (значения r) как значения, разделенные запятыми, поэтому сначала оценивают каждое из значений, разделенных запятыми.Это приводит к тому, что @b и @c назначаются, каждое из этих выражений также возвращает назначенные значения.

Тогда, поскольку @a - единственный элемент в левой части оператора присваивания, значения r обрабатываются какмассив, и массив назначается в @a.Значения состоят из a, b и c.Вот что произошло.

Итак, если вы хотите, чтобы выполнялись три назначения, то разделение назначений точкой с запятой, чтобы все операторы делались счастливыми для Ruby.

Обратите внимание, что вы можете указать несколькопредметы в левой части тоже =.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...