class.property = x를 가질 수 있습니까? x 이외의 다른 것을 반환 할 수 있습니까?
-
22-08-2019 - |
문제
루비 수업이 있다고 가정 해 봅시다.
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 기반/영감을받은 언어의 컨벤션입니다. Ruby의 "Equals Syntax"를 사용하여 세터를 위해이 작업을 수행 할 수 있습니까?
더욱이 - 이것이 불가능하다면 왜 그렇지 않습니까? "Equals Setter"작업을 허용하는 데 상상할 수있는 단점이 있습니까?
해결책
한 가지 단점은 당신이 사슬의 과제 의미를 깨뜨릴 것이라는 것입니다.
$ 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
분명히 그 표현의 반환 값은입니다 구현 특이 적... 나는 평행 할당을 연쇄하지 않을 것 같아요 :)
좋은 질문!
다른 팁
마틴이 말했듯이, 이것은 과제 체인을 깨뜨릴 것입니다.
루비 할당 방법이 작동하도록 정의되는 방식은 확장됩니다. 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
나는 루비 전문가가 아니지만 그 경우에 거절 할 것입니다. 재산 세터는 전적으로 개인 필드의 값을 설정하고 결과 코드를 반환하는 것과 같은 부작용이 없습니다.
그 기능을 원한다면 세터를 잊고 새로운 메소드를 작성하십시오. TrySetProperty
또는 재산을 설정하고 부울을 반환하려는 것.