Возможно ли, чтобы class.property = x возвращал что-то отличное от x?

Допустим, у меня есть класс Ruby:

class MyClass
  def self.property
    return "someVal"
  end

  def self.property=(newVal)
    # do something to set "property"
    success = true

    return success # success is a boolean
  end
end

Если я попытаюсь сделать MyClass.property=x, возвращаемое значение всего оператора всегда будет равно x. Во многих языках, основанных на C, существует соглашение о возвращении логического значения «success» - возможно ли это сделать для сеттера, использующего синтаксис «равно» в Ruby?

Кроме того - если это невозможно, почему бы и нет? Есть ли какие-либо мыслимые недостатки в том, что операция «Установка равных» может возвращать значение?

12 голосов | спросил Nick Forge 2 AMpThu, 02 Apr 2009 11:13:03 +040013Thursday 2009, 11:13:03

3 ответа


0

Недостатком является то, что вы нарушите семантику связанного присваивания:

$ irb 
irb(main):001:0> x = y = 3
=> 3
irb(main):002:0> p x
3
=> nil
irb(main):003:0> p y
3
=> nil
irb(main):004:0> 

Рассмотрим:

x = MyClass.property = 3

Тогда x получит true если это сработало так, как вы ожидали (правильная ассоциативность). Это может быть сюрпризом для людей, использующих ваш интерфейс и привыкших к типичной семантике.

Вы также заставили меня задуматься о параллельном назначении, например:

x, y = 1, 2

Видимо, возвращаемое значение из этого выражения зависит от конкретной реализации ... я думаю не будет цепочки параллельных назначений:)

Хороший вопрос!

ответил Martin Carpenter 2 PMpThu, 02 Apr 2009 12:14:22 +040014Thursday 2009, 12:14:22
0

Как говорит Мартин, это нарушит цепочку назначений.

То, как методы назначения ruby ​​определены для работы, расширяет MyClass.property = 3 до эквивалента (lambda { |v| MyClass.send('property=', v); v })[3] (не совсем, но это показывает, как работает цепочка). Возвращаемым значением присваивания всегда является присвоенное значение.

Если вы хотите увидеть результат вашего метода MyClass#property=, используйте #send:

irb> o = Object.new
=> #<Object:0x15270>
irb> def o.x=(y)
irb>   @x = y+1
irb>   puts "y = #{y}, @x = #@x"
irb>   true
irb> end
=> nil
irb> def o.x
irb>   puts "@x = #@x"
irb>   @x
irb> end
=> nil
irb> o.x = 4
y = 4, @x = 5
=> 4
irb> o.x
@x = 5
=> 5
irb> o.send('x=', 3)
y = 3, @x = 4
=> true

Тем не менее, рубиновый способ сделать это с исключениями - если что-то пойдет не так во время назначение, поднять исключение. Тогда все вызывающие должны справиться с этим, если что-то пойдет неверно, в отличие от возвращаемого значения, которое можно легко игнорировать:

# continued from above...
irb> def o.x=(y)
irb>   unless y.respond_to? :> and (y > 0 rescue false)
irb>     raise ArgumentError, 'new value must be > 0', caller
irb>   end
irb>   @x = y + 1
irb>   puts "y = #{y}, @x = #@x"
irb> end
=> nil
irb> o.x = 4
y = 4, @x = 5
=> 4
irb> o.x = 0
ArgumentError: new value must be > 0
    from (irb):12
    from :0
irb> o.x = "3"
ArgumentError: new value must be > 0
    from (irb):13
    from :0
irb> o.x
@x = 5
=> 5
ответил rampion 2 PMpThu, 02 Apr 2009 16:12:07 +040012Thursday 2009, 16:12:07
0

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

Если вы хотите эту функциональность, то забудьте установщик и напишите новый метод с именем TrySetProperty или что-то, что пытается установить свойство и возвращает логическое значение.

ответил Mark Pim 2 AMpThu, 02 Apr 2009 11:19:08 +040019Thursday 2009, 11:19:08

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132