문제

나는 여전히 루비를 처음 접했고 기본적으로 Cooper의 책을 마친 후 첫 마이크로 프로그래밍을 작성합니다. 나는 원숭이 패치를 피하는 방향을 지적했지만 문제는 동일한 행동을 달성하기위한 대안이 무엇인지 모른다는 것입니다. 기본적으로 모든 문자열 객체에서 액세스 할 수있는 새 메소드를 추가하고 싶습니다. 명백한 원숭이 패치 방법은 다음과 같습니다.

class String
  def do_magic
    ...magic...
  end
end

String.Send를 사용하는 방법이 있음을 기억합니다. 그러나 나는 그것이 어떻게 끝나고 어디서 읽었는지 기억할 수 없습니다. 누구든지 문자열 클래스 및 자식 객체에 해당 방법을 사용할 수있게 해줄 대안을 지적 할 수 있습니까?

도움이 되었습니까?

해결책

이 작업을 수행하는 다른 방법은 원숭이 패치를위한 더 어색한 구문 일 것입니다. 관련 방법이 있습니다 send 그리고 eval 그리고 모든 종류의 것들 ? 계속해서 명백한 방법으로하십시오.

큰 프로젝트에서 원숭이 패치 또는 의존성이있을 때는 여러 손이 같은 곳에서 엉망이 될 때 충돌에 맞춰야하기 때문에 원숭이 패치에주의를 기울이고 싶습니다. 그렇다고해서 같은 일을 달성하는 대체 구문을 찾는 것은 아닙니다. 이는 자신이 아닌 코드에 영향을 줄 수있는 변경을 할 때주의를 기울임을 의미합니다. 이것은 아마도 당신의 특정한 경우에 관심이 아닐 것입니다. 대규모 프로젝트에서 해결해야 할 수도 있습니다.

루비의 한 가지 대안은 단일 객체에 메소드를 추가 할 수 있다는 것입니다.

a = "Hello"
b = "Goodbye"
class <<a
  def to_slang
    "yo"
  end
end
a.to_slang # => "yo"
b.to_slang # NoMethodError: undefined method `to_slang' for "Goodbye":String

다른 팁

모든 문자열 객체에 액세스 할 수있는 새 메소드를 추가하려면 사용하는 방식으로 수행하는 방법을 수행하는 방법입니다.

모범 사례는 별도의 파일로 확장을 코어 객체에 넣는 것입니다. string_ex.rb) 또는 하위 디렉토리 (같은 extensions 또는 core_ext). 이런 식으로, 확장 된 것이 분명하며, 누군가가 어떻게 확장되거나 변경되었는지 쉽게 볼 수 있습니다.

원숭이 패치가 나빠질 수있는 곳은 원래 기능이 잘못 행동 할 것으로 예상되는 다른 코드를 일으키는 핵심 객체의 기존 동작을 변경할 때입니다.

그만큼 object 수업은 정의합니다 send, 그리고 모든 개체는 이것을 상속합니다. 당신은 물체를 "보내기" send 방법. 그만큼 send Method의 매개 변수는 기호로서의 메소드에서 want-to-invoke의 이름으로, 인수와 선택적 블록이 뒤 따릅니다. 당신은 또한 사용할 수 있습니다 __send__.

>> "heya".send :reverse
=> "ayeh"

>> space = %w( moon star sun galaxy )
>> space.send(:collect) { |el| el.send :upcase! }
=> ["MOON", "STAR", "SUN", "GALAXY"]

편집하다..

당신은 아마도 사용하고 싶을 것입니다 define_method 방법:

String.class_eval {
  define_method :hello do |name|
    self.gsub(/(\w+)/,'hello') + " #{name}"
  end
}

puts "Once upon a time".hello("Dylan")
# >> hello hello hello hello Dylan

인스턴스 메소드가 추가됩니다. 클래스 방법을 추가하려면 :

eigenclass = class << String; self; end
eigenclass.class_eval {
  define_method :hello do
    "hello"
  end
}

puts String.hello
# >> hello

그래도 블록을 기대하는 방법을 정의 할 수는 없습니다.

읽는 것이 좋을 수도 있습니다. 이 장에서 왜 Poignant Guide 의이 장, 당신은 "dwemthy의 배열"으로 건너 뛰면 메타 프로그래밍 물건에 도달 할 수 있습니다.

감사합니다.

제안 된 모든 구현 작업. 더 중요한 것은, 사례에 무게를 측정하고 코어 (또는 라이브러리) 클래스가 좋은 아이디어인지 아닌지를 결정하는 법을 배웠습니다.

Fwiw, 친구가 send 내가 찾고 있던 구현. 그러나 이제 내가 그것을 보았으므로, 그것은 다른 모든 구현보다 원숭이 삽입에 더 가깝습니다 :)

module M
    def do_magic
    ....
    end
end
String.send(:include, M)

클래스 또는 객체에 함수를 첨부하는 대안으로 항상 기능 경로를 가질 수 있습니다.

class StringMagic
  def self.do(string)
     ...
  end
end

StringMagic.do("I'm a String.") # => "I'm a MAGIC String!"

다른 사람이 코드를 요구하기를 원한다면 (예를 들어 보석) "원숭이 패치"는 실제로 문제가 될 수 있습니다. 누가 do_magic이라고 불리는 문자열 메소드를 추가하고 싶지 않다고 말하는 사람은 누구입니까? 한 메소드가 다른 방법을 덮어 쓰고 디버그하기가 어려울 수 있습니다. 코드가 오픈 소스가 될 가능성이 있으면 나만의 클래스를 만드는 것이 가장 좋습니다.

class MyString < String
  def initialize(str)
    @str = str
  end
  def do_magic
    ...magic done on @str
    @str
  end
end

이제 do_magic이 필요하다면 가능합니다

magic_str = MyString.new(str).do_magic
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top