2013-03-05 6 views
1

String에 몇 가지 새로운 메서드를 정의하려고합니다. 이 메소드가 다른 라이브러리에 정의 된 메소드와 충돌하지 않도록해야합니다 (참조 용으로, 굴곡자를 작성한 후 Stringpluralizesingularize 추가). 내 첫번째 생각네임 스페이스에서 문자열에 메서드 추가

그래서 같은 모듈에 새로운 물건을 포장했다 :

module MM 
    class String 
    def rev 
     self.split('').reverse.join('') 
    end 
    end 
end 

class Test 
    include MM 

    def me(s) 
    s.rev 
    end 
end 

puts Test.new.me('this is a test') 

그러나 물론이 작동하지 않습니다. String#rev은 정의되지 않은 상태로 유지됩니다. 내 코드에서 실제로 가지고있는 것은 모듈 MM이고 내장형 확장을 제외한 모든 것은 MM에 싸여있다. 내 목표는 Stringrev, singularizepluralize과 같은 메서드가 있지만 해당 모듈 내부에만 MM 인 방법을 사용하는 것입니다.

이것은 할 수있는 것처럼 보입니다. 그러나 어쨌든 나는 그렇게 할 수있는 비밀 주문을 놓치고있다.

누구나 제안 할 수 있다면 많은 도움이 될 것입니다.

+0

나는 완전히 이해하지 못한다. 자신의 클래스 내에서만 String을 확장하고 싶습니까? –

+0

내 모듈에서만. 이 구현을 다른 구현으로 돌리는 것을 피하기 만하면됩니다. 문제를 해결하기 위해 이름을 바꿀 수 있지만이 이름 공간은 디자인 된 것처럼 보입니다. –

+0

"관심사"가 무엇을 위해 설계 되었습니까? 동적으로 클래스 내에서 메소드를 정의/정의 해제하는 것은 약간 다릅니다. 모듈에서 메소드를 정의하고 특정 범위 내에서 사용할 수있는 메소드 만 갖는 것과는 다른 String에 넣으려는 경우. –

답변

2

"세부 조정"을 찾고 있습니다. 그것들은 Ruby 2.0의 실험적인 기능이므로, 2.0을 사용하지 않는다면 운이 없어 질 수도 있습니다. 나는 그들 자신을 아직 사용하지 않았지만, 당신의 예제는 거의 정련을위한 표준적인 사용 사례이다.

module StringHelper 
    def rev 
    self.split('').reverse.join('') 
    end 
end 

class Test 
    def me(s) 
    s.extend(StringHelper).rev 
    end 
end 

또는 서브 클래스 문자열 : A와

class StringPlus < String 
    def rev 
    self.split('').reverse.join('') 
    end 
    def self.[](s) 
    new(s) 
    end 
end 

class Test 
    def me(s) 
    StringPlus[s].rev 
    end 
end 
+1

진술 : 이것은 작동하지 않습니다. 필자가 몇 분 전에이 글을 읽었을 때, 당신이 위에 쓴 것을 적어 두었습니다 .- 최근에는 그랬지만, 2.0.0-p0이 출시되기 직전에 Refinements의 스펙이 변경되었습니다. 특히,'using'은 최상위'main' 객체의 private 싱글 톤 메소드로 정의됩니다. 즉, 최상위 범위에서만 * 사용할 수 있음을 의미합니다. 따라서 Refinements *는 항상 * 전체 * 파일과 * 내부의 모든 모듈과 클래스에 적용됩니다 (물론'using' 호출 이후에만 적용됩니다). –

+0

클래스 나 모듈 선언 내에서'using'을 호출하면 해당 범위 내에서만 구체화가 적용됩니다 * 최근까지 작동했으며 * 향후 * 작동하지만 * Ruby 2.0의 릴리스 버전에서는 사용 불가능합니다. 불행히도, 모든 블로그 게시물과 실제로 StackOverflow에 대한 내 대답은 그 사용법을 정확하게 보여줍니다. –

+0

아, 스냅. 나는 1.9에 지금 붙어있다. 내 메소드 인 mm_singularize 또는 mm_pluralize의 이름을 지정하는 무차별 방식을 사용하겠습니다. 언어 문제 (IMO) - 특히 여러 라이브러리 (보석)가 비슷한 방법을 필요로하거나 구현할 가능성이 있지만 ActiveSupport에 의존하지 않으려 고 할 때 그렇습니다. –

0

글쎄, 문자열 클래스를 분리 할 수있는 또 다른 방법이 있습니다. 당신이 요구를 추가 할 때까지 모든 것이 무료가 될 것입니다.

#my_string.rb 
class String 
    def rev 
     self.split('').reverse.join('') 
    end 
end 

#test.rb 
class Test 
    require 'F:\on going\New Site\Ruby\my_string.rb' # Assuming both these files are in the same folder 


    def me(s) 
    s.rev 
    end 
end 


puts Test.new.me('this is a test') 
+0

은'NoMethodError : undefined method 'rev "에 대해"this is a test "를 제공합니다 : String' – AnkitG

+0

그것은'문자열'의 메소드에'rev'가 추가되지 않기 때문입니다. 메소드 'm'은 단순히 'Test'클래스의 인스턴스 메소드이기 때문에 작동합니다. 나는's.rev'가 일하기를 바라고 있습니다. –

+0

지적 해 주셔서 감사합니다 : D – sadaf2605

2

부족 개선 : 사용자가 원하는 동작을 얻을 수있는 refineusing 키워드를 사용 세련미가없는 상황에서이 문제가 해결된다고 알았습니다 :

# class String 
# def rev 
#  puts "rev: #{self}" 
# end 
# end 

class String 
    unless String.instance_methods.include?(:rev) 
    def rev 
     self.split('').reverse.join('') 
    end 
    end 
end 

class Test 
    def me(s) 
    s.rev 
    end 
end 

puts Test.new.me('this is a test') 

이전 정의 인 rev의 주석 처리를 제거하면 무시되지 않으며 무시되지 않습니다. 이것은 약간 해키이며 파일이로드되는 순서에 따라 다르지만로드 순서가 제어되면 작동합니다.

+0

이 제안에 감사드립니다. 그것은 제가 바라보고있는 방향 중 하나였습니다. 내가 직면 한 문제는 이러한 객체가 사용자에 의해 나에게 던져 질 수 있고 유형이 'case' 문으로 나올 때까지 알 수 없다는 것입니다. 제 코드는 보석에 있습니다. 문자열일지도 모르는 모든 것에 대해'StringPlus'를 명시 적으로 생성하는 것은 코드 냄새처럼 보입니다. 내 확장 기능의 이름을 바꾸면 내게 어떤 의미인지 알면 '더티'느낌이 덜 날 것입니다. –

0

개별 문자열 객체를 확장 할 수

module MM 
    refine class String 
    def rev 
     self.split('').reverse.join('') 
    end 
    end 
end 

class Test 
    using MM 

    def me(s) 
    s.rev 
    end 
end 

puts Test.new.me('this is a test') 
관련 문제