2009-04-15 32 views

Trả lời

166

Tôi nghĩ rằng trong Ruby 1.9 bạn có thể làm điều này:

class A 
    define_singleton_method :loudly do |message| 
    puts message.upcase 
    end 
end 

A.loudly "my message" 

# >> MY MESSAGE 
+3

Xác nhận làm việc trong 1.9.2p0 – bloudermilk

+3

cũng 'singleton_class.define_method' – Pyro

8

Xuất phát từ: JayWhy, người cũng cung cấp cách để làm đẹp này.

self.create_class_method(method_name) 
    (class << self; self; end).instance_eval do 
    define_method method_name do 
     ... 
    end 
    end 
end 

Cập nhật: từ sự đóng góp của VR dưới đây; một phương pháp ngắn gọn hơn (miễn là bạn chỉ định một phương pháp theo cách này) mà vẫn độc lập:

self.create_class_method(method_name) 
    (class << self; self; end).send(:define_method, method_name) do 
    ... 
    end 
end 

nhưng lưu ý rằng việc sử dụng send() để truy cập vào các phương pháp riêng như define_method() không nhất thiết là tốt ý tưởng (sự hiểu biết của tôi là nó sẽ biến mất trong Ruby 1.9).

+0

tốt hơn (?) thay thế có thể được đặt những thứ trong một mô-đun và sau đó có create_class_method của bạn mở rộng các mô-đun vào lớp ??? Xem: http://blog.jayfields.com/2008/07/ruby-underuse-of-modules.html – Chinasaur

22

Tôi thích sử dụng gửi đến gọi define_method, và tôi cũng muốn tạo ra một phương pháp metaclass để truy cập metaclass:

class Object 
    def metaclass 
    class << self 
     self 
    end 
    end 
end 

class MyClass 
    # Defines MyClass.my_method 
    self.metaclass.send(:define_method, :my_method) do 
    ... 
    end 
end 
+2

Cảm ơn! Chắc chắn có nhiều cách để làm đẹp hơn cho chính bạn. Nhưng nếu bạn đang làm việc trên một plugin nguồn mở, ví dụ, tôi nghĩ rằng nó đẹp hơn không làm tắc nghẽn không gian tên với 'metaclass', do đó, nó là tốt đẹp để biết viết tắt dễ dàng, độc lập. – Chinasaur

+0

Tôi quyết định đi với câu trả lời ban đầu của mình. Sự hiểu biết của tôi là sử dụng send() để truy cập các phương thức riêng nếu đi xa trong Ruby 1.9, vì vậy điều đó dường như không phải là một điều tốt để sử dụng. Thêm vào đó nếu bạn định nghĩa nhiều hơn một phương thức, instance_evaling một khối sẽ sạch hơn. – Chinasaur

+0

@Vincent Robert bất kỳ liên kết nào sẽ giải thích sự kỳ diệu của phương pháp metaclass? –

8

Đây là cách đơn giản nhất trong Ruby 1.8+:

class A 
    class << self 
    def method_name 
     ... 
    end 
    end 
end 
+1

Tôi thực sự thích cái này. Nhỏ, gọn gàng, đọc tốt và có thể cầm tay. Tất nhiên, bạn có thể hỏi tôi đang làm gì với ruby ​​1.8 vào năm 2013 ... –

4

Được sử dụng trong Rails nếu bạn muốn xác định phương thức lớp s động từ mối quan tâm:

module Concerns::Testable 
    extend ActiveSupport::Concern 

    included do 
    singleton_class.instance_eval do 
     define_method(:test) do 
     puts 'test' 
     end 
    end 
    end 
end 
-1

Bạn cũng có thể làm một cái gì đó như thế này mà không dựa vào define_method:

A.class_eval do 
    def self.class_method_name(param) 
    puts param 
    end 
end 

A.class_method_name("hello") # outputs "hello" and returns nil 
-2

này làm việc cho tôi trong Ruby 1.9.3

class B 
    def self.class_method(param) 
     puts param 
    end 
end 

B.class_method("something") # outputs "something". 
+0

OP đã yêu cầu các cách định nghĩa động các phương thức lớp tương tự như cách các phương thức có thể được định nghĩa bằng phương thức 'define_method' để định nghĩa các phương thức instance. Câu trả lời của bạn chỉ là cách đơn giản mà các phương thức được định nghĩa bình thường mà không cần lập trình meta. –

+1

Có vẻ như tôi đã hiểu nhầm câu hỏi. – Greg

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