Ruby 갈고리 방법의 활용 실례 해석

5765 단어 Ruby갈고리 방법
갈고리 방법을 사용하면 루비의 클래스나 모듈의 생명주기에 관여할 수 있고 프로그래밍의 유연성을 크게 높일 수 있다.
라이프 사이클과 관련된 갈고리 방법은 다음과 같습니다.
클래스와 모듈 관련
  • Class#inherited
  • Module#include
  • Module#prepended
  • Module#extend_object
  • Module#method_added
  • Module#method_removed
  • Module#method_undefined
  • 단품류 관련
  • BasicObject#singleton_method_added
  • BasicObject#singleton_method_removed
  • BasicObject#singleton_method_undefined
  • 예제 코드
    
    module M1
      def self.included(othermod)
        puts “M1 was included into #{othermod}”
      end
    end
    
    module M2
      def self.prepended(othermod)
        puts “M2 was prepended to #{othermod}”
      end
    end
    
    class C
      include M1
      include M2
    end
    
    #  
    M1 was included into C
    M2 was prepended to C
    
    module M
      def self.method_added(method)
        puts “New method: M##{method}”
      end
    
      def my_method; end
    end
    
    #  
    New method: M#my_method
    
    
    위에서 열거한 몇 가지 방법을 제외하고 부류의 어떤 방법을 다시 쓰고 필터 조작을 한 후에 슈퍼 방법을 호출하여 원 함수의 기능을 완성하여 유사한 갈고리 방법의 효능을 실현할 수 있다. 예를 들어 별명을 둘러싼 것도 갈고리 방법의 대체로 실현될 수 있다.
    활용 실례
    작업 설명:
    attr_와 같은 조작 방법 쓰기accessor의attr_checked의 클래스 매크로, 이 클래스 매크로는 속성 값을 검사하는 데 사용됩니다. 사용 방법은 다음과 같습니다.
    
    class Person
     include CheckedAttributes
    
     attr_checked :age do |v|
      v >= 18
     end
    end
    
    me = Person.new
    me.age = 39 #ok
    me.age = 12 # 
    
    
    구현 계획:
    eval 방법을 사용하여add_checked_attribute의 내부 핵 방법, 지정한 클래스에 간단한 검사를 거친 속성을 추가합니다
    재구성add_checked_attribute 방법, eval 방법을 제거하고 다른 수단으로 실현
    코드 블록 검증 기능 추가
    add_ 수정checked_attribute가 요구하는 attr_checked, 모든 클래스에 사용 가능
    모듈을 도입하는 방식으로 이 기능 모듈을 도입한 클래스에attr_checked 방법
    Step 1
    
    def add_checked_attribute(klass, attribute)
     eval "
      class #{klass}
       def #{attribute}=(value)
        raise 'Invalid attribute' unless value
        @#{attribute} = value
       end
       def #{attribute}()
        @#{attribute}
       end
      end
     "
    end
    
    add_checked_attribute(String, :my_attr)
    t = "hello,kitty"
    
    t.my_attr = 100
    puts t.my_attr
    
    t.my_attr = false
    puts t.my_attr
    
    
    이 단계는 eval 방법을 사용하여class와 def 키워드로 각각 클래스를 열고 지정한 속성의 get과 set 방법을 정의합니다. 그 중의 set 방법은 값이 비어 있는지 (nil 또는false) 있는지 간단하게 판단하고 Invalid attribute 이상을 던집니다.
    Setp 2
    
    def add_checked_attribute(klass, attribute)
     klass.class_eval do
      define_method "#{attribute}=" do |value|
       raise "Invaild attribute" unless value
       instance_variable_set("@#{attribute}", value)
      end
    
      define_method attribute do
       instance_variable_get "@#{attribute}"
      end
    
     end
    end
    
    
    이 단계에서 eval 방법을 교체하였으며, 동시에 각각class_eval 및 define_method 방법은 이전의class와 def 키워드를 대체하였으며, 실례 변수의 설정과 획득은 각각 instance_로 변경되었습니다variable_set 및 instance_variable_get 방법, 사용은 첫 번째 단계와 아무런 차이가 없고 내부적으로 이루어진 차이일 뿐입니다.
    Step 3
    
    def add_checked_attribute(klass, attribute, &validation)
     klass.class_eval do
      define_method "#{attribute}=" do |value|
       raise "Invaild attribute" unless validation.call(value)
       instance_variable_set("@#{attribute}", value)
      end
    
      define_method attribute do
       instance_variable_get "@#{attribute}"
      end
    
     end
    end
    
    add_checked_attribute(String, :my_attr){|v| v >= 180 }
    t = "hello,kitty"
    
    t.my_attr = 100 #Invaild attribute (RuntimeError)
    puts t.my_attr
    
    t.my_attr = 200
    puts t.my_attr #200
    
    
    특이한 것은 없다. 단지 코드 블록 검증을 통해 검사의 유연성을 증가시켰을 뿐이다. 더 이상nil과false 사이에만 국한되지 않는다.
    Step 4
    
    class Class
     def attr_checked(attribute, &validation)
       define_method "#{attribute}=" do |value|
        raise "Invaild attribute" unless validation.call(value)
        instance_variable_set("@#{attribute}", value)
       end
    
       define_method attribute do
        instance_variable_get "@#{attribute}"
       end
     end
    end
    
    String.add_checked(:my_attr){|v| v >= 180 }
    t = "hello,kitty"
    
    t.my_attr = 100 #Invaild attribute (RuntimeError)
    puts t.my_attr
    
    t.my_attr = 200
    puts t.my_attr #200
    
    
    여기서 우리는 이전의 최고급 작용 영역에서 방법명을 Class에 넣었습니다. 모든 대상이 Class의 실례이기 때문에 여기서 정의한 실례 방법은 루비의 다른 모든 클래스에 접근할 수 있습니다. 동시에class 정의에서self는 현재 클래스이기 때문에 호출 클래스라는 매개 변수와class_를 절약했습니다.eval 방법, 그리고 방법의 이름도attr_로 바꿨습니다.checked.
    Step 5
    
    module CheckedAttributes
     def self.included(base)
      base.extend ClassMethods
     end
    end
    
    module ClassMethods
     def attr_checked(attribute, &validation)
       define_method "#{attribute}=" do |value|
        raise "Invaild attribute" unless validation.call(value)
        instance_variable_set("@#{attribute}", value)
       end
    
       define_method attribute do
        instance_variable_get "@#{attribute}"
       end
     end
    end
    
    class Person
     include CheckedAttributes
    
     attr_checked :age do |v|
      v >= 18
     end
    end
    
    
    마지막 단계는 갈고리 방법을 통해 Checked Attributes 모듈이 도입된 후에 현재 클래스가 도입된 모듈을 통해 확장되어 현재 클래스가 도입된 방법을 호출합니다. 즉, 이곳의 get과 set 방법 그룹입니다.
    여기까지, 우리는 이미 attr_라는 이름을 얻었다checked, 유사attr_accessor의 클래스 매크로를 통해 속성을 원하는 대로 검사할 수 있습니다.

    좋은 웹페이지 즐겨찾기