Pergunta

Vamos dizer que eu tenho uma classe 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

Se eu tentar fazer MyClass.property=x, o valor de retorno de toda a declaração é sempre x. É uma convenção em um monte de base de C / idiomas inspirados para retornar um valor booleano "sucesso" - é possível fazer isso por um setter usando o "é igual a sintaxe" em Ruby

?

Além disso - se isso não for possível, por que não? Existe alguma desvantagem concebível para permitir uma operação "igual setter" retornar um valor?

Foi útil?

Solução

Uma desvantagem é que você iria quebrar a semântica de atribuição encadeadas:

$ 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> 

Considere o seguinte:

x = MyClass.property = 3

Então x levaria true se isso funcionou como você esperava (direita-associatividade). Isso poderia ser uma surpresa para as pessoas que utilizam a sua interface e usado para a semântica típicos.

Você também me fez pensar sobre a atribuição paralela, por exemplo:

x, y = 1, 2

Aparentemente, o valor de retorno a partir dessa expressão é implementação específica ... Eu acho que eu não será encadeamento atribuições paralelas:)

pergunta agradável!

Outras dicas

Como Martin diz, isso iria quebrar atribuição encadeamento.

Os métodos de atribuição de rubi forma como são definidos para o trabalho se expande MyClass.property = 3 para o equivalente a (lambda { |v| MyClass.send('property=', v); v })[3] (não realmente, mas isso mostra como o encadeamento de obras). O valor de retorno da atribuição é sempre o valor atribuído.

Se você quiser ver o resultado do seu método MyClass#property=, em seguida, usar #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

No entanto, a maneira de rubi de fazer isso é com exceções - se algo der errado durante a atribuição, levantar uma exceção. Em seguida, todos os solicitantes devem lidar com isso, se algo der errado, ao contrário de um valor de retorno, que pode ser facilmente ignorado:

# 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

Eu não sou um especialista em Rubi, mas eu diria que não para esse caso, eu estou com medo. Uma propriedade setter é apenas lá para definir o valor de um campo privado, não tem quaisquer efeitos colaterais como retornando códigos de resultado.

Se você quiser que a funcionalidade em seguida, esquecer o setter e escrever um novo método chamado TrySetProperty ou algo que tenta definir a propriedade e retorna um boolean.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top