2014-02-11 2 views
2

String 클래스를 실제로 열지 않고도 문자열 개체에 다양한 메서드를 연결하는 방법을 찾고 있습니다 (또는 모범 사례). 이것은 String 객체에 적용하려는 변형이 프로젝트마다 상당히 다르므로 전역 공간을 지정하는 이유를 알지 못하기 때문입니다.코어 확장이없는 문자열의 체인 메서드

이 방법이 있습니까? 어쩌면 어떤 종류의 포장지일까요? 나는 experiment으로 실험했다. gsub가 일치하지 않으면 nil을 던지지 않는 한 인스턴스 변수에서 gsub!를 실행하므로 달성하려는 연결을 중단합니다.

"my_string".transformation1.transformation2.transformation3

을 내 응용 프로그램에 네임 스페이스 모든 변환을 계속 얻을 :

기본적으로, 나는 할 수 있어야합니다. 어떤 아이디어?

+2

항상 인스턴스에 추가 할 수 있습니다. –

+0

@DaveNewton 할 수 있습니다. 그러나 이러한 모든 변환이 동일하므로 비용이 많이 듭니다. –

+0

... 그런 다음 문자열에 추가하거나 "우려"구현을 사용하십시오. 조금 비싸기도합니다. –

답변

4

당신은 인스턴스에 메서드를 추가 할 수 있지만이 방법 체인 농구 대를 통해 이동할 필요 해요 :

str = 'now is the time' 

def str.foo(target, replacement) 
    self.gsub(target, replacement) 
end 

def str.bar 
    self.reverse 
end 

str.singleton_methods # => [:foo, :bar] 
str.foo('ow', 'ever') # => "never is the time" 
str.bar # => "emit eht si won" 

이 작동하지 않습니다 :

str.foo('ow', 'ever').bar 

# ~> NoMethodError 
# ~> undefined method `bar' for "never is the time":String 

"bang"형식의 메서드를 사용하면 원래의 개체를 변형 할 수 있습니다.

str = 'now is the time' 

def str.foo(target, replacement) 
    self.gsub!(target, replacement) 
    self 
end 

def str.bar 
    self.reverse! 
    self 
end 

str.singleton_methods # => [:foo, :bar] 

str.foo('ow', 'ever').bar # => "emit eht si reven" 

비록주의해야합니다. 이것은 모든 유형의 객체에서 작동하지 않으며, 변이를 허용하는 객체에서만 작동합니다.

그리고 추가 된 메서드가 특정 변수에서만 사용 가능하다는 사실은 실제로 제한적입니다. 동일한 기능을 재사용하는 것이 지저분합니다. 당신은 변수를 clone 새로운 변수에 그 클론을 할당하지만 다른 뭔가 값을 대체하는 것은 혼란하게 할 수 있습니다 개인적으로

str2 = str.clone 
str.object_id # => 70259449706680 
str2.object_id # => 70259449706520 
str.singleton_methods # => [:foo] 
str2.singleton_methods # => [:foo] 

str2 = 'all good men' 
str2.foo('ll', '') # => 

# ~> NoMethodError 
# ~> undefined method `foo' for "all good men":String 

, 나는 서브 클래스를 통해 그것을 할 것 :

class MyString < String 
def foo(s, t) 
    self.gsub(s, t) 
end 
end 

str = MyString.new('now is the time') 
str.foo('ow', 'ever') # => "never is the time" 

str2 = 'all good men' 
str2.foo('ll', '') # => 

# ~> NoMethodError 
# ~> undefined method `foo' for "all good men":String 

Ruby v2 +를 사용하는 경우 구체화를 사용하여 @ mdesantis의 대답을 살펴보십시오. 이런 종류의 문제를 해결하기 위해 도입되었습니다. < v2.0 인 경우 하위 클래스 경로로 이동하거나 String을 수정해야합니다. 루비> = 2.0을 사용하는 경우

+0

서브 클래 싱과 함께갔습니다. 훨씬 더 깨끗하고 응용 범위가 매우 넓습니다. –

7

당신은 refinements를 사용할 수 있습니다

module MyRefinements 
    refine String do 
    def transformation1 
     # ... 
     self 
    end 
    def transformation2 
     # ... 
     self 
    end 
    def transformation3 
     # ... 
     self 
    end 
    end 
end 

# Either in global scope (active until the end-of-file) 
# or in lexical scope (active until the lexical scope end) 
# More on this in the refinements docs scope section 

# global scope 
using MyRefinements 
"test".transformation1.transformation2.transformation3 #=> "test" 

# lexical scope 
begin 
    using MyRefinements 
    "test".transformation1.transformation2.transformation3 #=> "test" 
end 
+0

+1. 나는 정련을 잊었다. 새롭고 신나는 것들을 던지십시오. :-) –

+0

@theTinMan 필자는 아직 프로덕션 코드에서 사용하지 않았다는 것을 인정해야합니다. 그러나 나는 그 (것)들을 아주 똑똑한 찾아 냈다, 나는 다음 기회에 그 (것)들을 사용할 것이다 – mdesantis

+0

감사합니다 @mdesantis. 나는 그 (것)들을 또한 좋아하고 그러나 subclassing로 가기 끝냈다. –

관련 문제