Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby 정제 및 어휘 범위 이해

이전에 미세 조정을 사용한 적이 없다면 아마 놀랄 것입니다. 원숭이 패치를 대체하기 위해 개선 사항이 도입되었다는 소식을 들었을 것입니다. 따라서 ActiveSupport의 hours 방법:

module TimeExtension
  refine Fixnum do
    def hours
      self * 60
    end
  end
end

class MyFramework
  using TimeExtension
end

class MyApp < MyFramework
  def index
    1.hours
  end
end

MyApp.new.index # undefined method `hours' for 1:Fixnum (NoMethodError)

위의 코드를 실행하면 작동하지 않는다는 것을 알 수 있습니다. 그래서 무엇을 제공합니까?

다른 많은 훌륭한 아이디어와 마찬가지로 냉정한 현실에서 작동하도록 하려면 개선의 원래 개념을 조정해야 했습니다.

위에서 살펴본 코드의 놀라운 동작은 이러한 조정 중 하나로 인해 발생합니다. 구체적으로, 구체화는 어휘 범위를 지정한다는 규칙입니다.

어휘 범위 지정이란 무엇입니까?

어떤 것이 어휘적이라고 말할 때 그것은 텍스트와 관련이 있음을 의미합니다. 즉, 그 코드가 의미하는 것과는 대조적으로 화면에 표시되는 코드입니다.

두 줄의 어휘 범위가 지정되면 해당 코드 블록이 평가할 대상에 관계없이 동일한 코드 블록 내에서 발생한다는 의미입니다.

이야기하는 것보다 예제를 보는 것이 훨씬 쉽습니다.

class B
  # x and y share the same lexical scope
  x = 1
  y = 1
end

class B
  # z has a different lexical scope from x and y, even though it's in the same class. 
  z = 3
end

세련 항목은 어휘 범위가 지정됩니다.

using 키워드로 구체화를 적용하면 구체화는 어휘 범위 내에서만 볼 수 있습니다.

다음은 내가 의미하는 바를 보여주는 예입니다.

module TimeExtension
  refine Fixnum do
    def hours
      self * 60
    end
  end
end

class MyApp
  using TimeExtension
  def index
    1.hours
  end
end

class MyApp
  def show
    2.hours
  end
end

MyApp.new.show # undefined method `hour' for 1:Fixnum (NoMethodError)

indexshow 메소드는 동일한 클래스의 일부이며 index만 메소드는 using과 어휘 범위를 공유하기 때문에 구체화에 액세스할 수 있습니다. 성명서.

Ruby의 다른 거의 모든 것이 동적으로 범위가 지정되기 때문에 이것은 아마도 약간 이상하게 보일 것입니다. 클래스에 메서드를 추가하면 클래스 정의를 종료할 때 메서드가 그대로 유지됩니다. 그러나 개선 작업은 그렇지 않습니다.

이것은 처음에는 분명하지 않을 수 있는 여러 가지 결과입니다.

정제 방법을 동적으로 호출할 수 없습니다.

send 메소드가 using 문이 포함된 동일한 코드 블록 내에서 정의되지 않아 세분화를 볼 수 없습니다.

그래서 이것은 작동하지 않습니다:

class MyApp
  using TimeExtension
  def index
    1.send(:hours)
  end
end

세련 방법의 존재를 쿼리할 수 없습니다.

respond_to? 메소드도 동일한 코드 블록 내에 있지 않습니다. 따라서 send와 같은 이유로 작동하지 않습니다. 방법이 없습니다.

class MyApp
  using TimeExtension
  def index
    1.respond_to?(:hours)
  end
end

결론

이것이 사람들이 개선에 대해 가지고 있는 혼란을 해결하기를 바랍니다. 확실히 Ruby의 잠재적으로 유용한 기능이지만 이전에 사용해 본 적이 없다면 약간 까다로울 수 있습니다.