2012-11-15 40 views
6

Tôi có một mô-đun cho phép gọi "Máy tính" mà tôi muốn đưa vào lớp "Sản phẩm". Máy tính sẽ mở rộng "Sản phẩm" sẽ sao chép các phương thức lớp vào Sản phẩm. Một trong những phương thức lớp này là "ghi nhớ". Ý tưởng là tôi có thể làm một cái gì đó như thế này:Làm cách nào tôi có thể xác định động một phương thức bí danh cho một phương thức lớp?

module Calculator 
    def self.extended(base) 
    base.memoize :foo_bar 
    end 
end 

Với mục đích ghi nhớ phương pháp (cụ thể là một phương pháp lớp): foo_bar. Bên trong của memoize tôi gọi phương thức "alias_method" mà cố gắng để alias một method class thành một tên khác (ở đây: foo_bar). Điều này không thành công. Memoize trông giống như sau:

module Calculator (the extended module) 
    def memoize(name) 
    alias_method "memoized_#{name}", name 
    end 
end 

Khi điều này được gọi là qua memoize: foo_bar, dòng alias_method đá một lỗi nói rằng sản phẩm không có phương pháp "tên" .. hiểu biết của tôi là điều này là do alias_method sẽ cố gắng bí danh phương pháp dụ không phương pháp lớp học .. (tôi không biết tại sao nhưng ok không có vấn đề lớn) ..

tôi có thể mở lại eigenclass như vậy

module Calculator 
    def memoize(name) 
    class << self 
     alias_method "memoized_#{name}", name 
    end 
    end 
end 

này sẽ làm việc nhưng tên không có sẵn cho phạm vi lớp < < s elf định nghĩa. Mọi người đã đề cập đến bằng cách sử dụng self.class_eval và self.instance_eval nhưng không phải của những dường như làm việc .. Tôi muốn bánh của tôi và ăn nó quá .. làm thế nào tôi có thể giữ alias_method năng động nhưng sử dụng nó trên class_methods?

Trả lời

3

Vì vậy, chỉ biết rằng điều này sẽ làm các trick:

module Calculator 
    def memoize 
    define_singleton_method(name, method(name)) 
    end 
end 

Sau đó, khi tính được bao gồm trong sản phẩm đó sẽ xác định phương pháp singleton như tôi cần. Tôi vẫn không biết tại sao alias_method cần phải chỉ làm việc trên các phương pháp dụ .. và tôi không biết tại sao class_eval hoặc instance_eval không giải quyết vấn đề .. nhưng ít nhất tôi có một giải pháp ..

3

Điều gì xảy ra nếu bạn đặt phương thức cá thể để được đặt bí danh trước khi bao gồm/mở rộng? Nếu bạn đang đặt phần mở rộng ngay sau tên lớp, phương thức thể hiện sẽ chưa được xác định.

module Foo 
    def self.extended(base) 
    base.memoize :flavor 
    end 

    def memoize(name) 
    alias_method "memoized_#{name}", name 
    end 
end 

class Bar 
    def flavor 
    puts "Orange" 
    end 

    extend Foo 
end 

if __FILE__==$0 
    b = Bar.new 
    b.memoized_flavor #=> Orange 
end 
+0

Trong khi một ý tưởng tốt này thực sự không phải là tình huống khi phương thức được đặt bí danh được mở rộng trong mô-đun và được mở rộng trước khi thực hiện bí danh. Mặc dù vậy, suy nghĩ tuyệt vời. – Inc1982

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