2009-04-29 24 views
28

Trong Ruby, có cách nào để xác định lại một phương thức của một cá thể cụ thể của một lớp bằng cách sử dụng một proc không? Ví dụ:xác định lại phương thức ruby ​​đơn trên một cá thể đơn với một lambda

class Foo 
    def bar() 
    return "hello" 
    end 
end 

x = Foo.new 
y = Foo.new 

(Một cái gì đó tương tự):

y.method(:bar) = lambda { return "goodbye" } 

x.bar 
y.bar 

Sản xuất:

hello 
goodbye 

Cảm ơn.

Trả lời

40
def define_singleton_method_by_proc(obj, name, block) 
    metaclass = class << obj; self; end 
    metaclass.send(:define_method, name, block) 
end 
p = proc { "foobar!" } 
define_singleton_method_by_proc(y, :bar, p) 

hoặc, nếu bạn muốn đối tượng khỉ vá để làm cho nó dễ dàng

class Object 
    # note that this method is already defined in Ruby 1.9 
    def define_singleton_method(name, callable = nil, &block) 
    block ||= callable 
    metaclass = class << self; self; end 
    metaclass.send(:define_method, name, block) 
    end 
end 

p = proc { "foobar!" } 
y.define_singleton_method(:bar, p) 
#or 
y.define_singleton_method(:bar) do 
    "foobar!" 
end 

hoặc, nếu bạn muốn xác định inline proc của bạn, điều này có thể dễ đọc hơn

class << y 
    define_method(:bar, proc { "foobar!" }) 
end 

hoặc,

class << y 
    define_method(:bar) { "foobar!" } 
end 

đây là mo st có thể đọc được, nhưng có lẽ không phù hợp với nhu cầu của bạn

def y.bar 
    "goodbye" 
end 

This question is highly related

15

Bạn có thể sử dụng cú pháp class <<object để có được "lớp singleton" của một đối tượng (đó là một lớp cha mẹ đặc biệt chỉ thuộc đối tượng đó) và chỉ định nghĩa các phương thức cho cá thể đó. Ví dụ:

str1 = "Hello" 
str2 = "Foo" 

class <<str1 
    def to_spanish 
    'Hola' 
    end 
end 

Bây giờ nếu bạn làm str1.to_spanish, nó sẽ trở lại "Hola", nhưng str2.to_spanish sẽ cung cấp cho bạn một ngoại lệ NoMethodFound.

+0

nếu anh ta có một proc được xác định bên ngoài trong một biến đơn giản, rất khó để đưa nó vào phạm vi mới được tạo bởi lớp << str1, mà không cần đến các biến toàn cục hoặc thể hiện –

19

Tôi không chắc chắn những gì phiên bản của Ruby này đã được bổ sung trong (ít nhất là 1.8.7), nhưng có vẻ là một cách đơn giản hơn để làm điều này:

str1 = "Hello" 
str2 = "Goodbye" 
def str1.to_spanish 
    "Hola" 
end 
puts str1 # => Hello 
puts str1.to_spanish # => Hola 
puts str2 # => Goodbye 
puts str2.to_spanish # => Throws a NoMethodError 

học kinh nghiệm về vấn đề này trong khi đọc Ruby Koans (bài học about_class_methods.rb). Tôi vẫn không hoàn toàn chắc chắn mục đích của việc này là vì nó có vẻ hơi nguy hiểm đối với tôi.

+0

Cảm ơn bạn đã đăng bài này (thêm) -date trả lời! –

+0

Giả sử 'str.to_spanish' đã được xác định và tôi muốn" xác định lại "nó, làm thế nào tôi sẽ gọi là" gốc "' str.to_spanish' từ bên trong định dạng mới được xác định? –

+0

Nếu 'str' là đối tượng thể hiện của bạn và' String' là lớp của bạn, bạn có thể gọi phiên bản của lớp của phương thức bằng 'String.to_spanish' – BRFennPocock

Các vấn đề liên quan