Tôi đã cố gắng thiết lập một hệ thống nhờ đó tôi có thể tạo ra một loạt các lớp Ruby tương tự, được phân biệt bởi tham số nguyên, mà tôi lưu vào một biến lớp của lớp có liên quan - giống như các mẫu C++.Các lớp được định nghĩa động không chính xác chia sẻ dữ liệu - lỗi hoặc lỗi mã hóa?
Tuy nhiên, tham chiếu (do đó, tạo) một phiên bản mới của lớp templated sẽ ghi đè các tham số đã lưu trong các phiên bản trước và tôi không thể giải thích tại sao.
Dưới đây là một ví dụ rất nhỏ
class Object
def self.const_missing(name)
if name =~ /^Templ(\d+)$/
return make_templ $1.to_i
else
raise NameError.new("uninitialised constant #{name}")
end
end
private
def make_templ(base)
# Make sure we don't define twice
if Object.const_defined? "Templ#{base}"
return Object.const_get "Templ#{base}"
else
# Define a stub class
Object.class_eval "class Templ#{base}; end"
# Open the class and define the actual things we need.
Object.const_get("Templ#{base}").class_exec(base) do |in_base|
@@base = in_base
def initialize
puts "Inited with base == #{@@base}"
end
end
Object.const_get("Templ#{base}")
end
end
end
irb(main):002:0> Templ1.new
Inited with base == 1
=> #<Templ1:0x26c11c8>
irb(main):003:0> Templ2.new
Inited with base == 2
=> #<Templ2:0x20a8370>
irb(main):004:0> Templ1.new
Inited with base == 2
=> #<Templ1:0x261d908>
Tôi đã tìm thấy một lỗi trong Ruby của tôi (ruby 1.9.2p290 (2011/07/09) [i386-mingw32]), hoặc đã tôi chỉ đơn giản là mã hóa một cái gì đó sai?
Tôi đã dành 45 phút để tìm ra điều này, và tôi đoán có điều gì đó sai với các ràng buộc biến vì bạn đang chạy một khối bên trong lớp 'Object'. Tuy nhiên tôi không thể lấy tín dụng cho câu trả lời vì cuối cùng tôi đã tìm thấy lời giải thích như bị nghi ngờ ở đây: http://stackoverflow.com/questions/10109925/ruby-unexpected-results-from-class-exec-when-defining-class- biến. Giải pháp của bạn là chuyển đổi khối đó thành chuỗi và đánh giá nó thay vì vậy nó sẽ được biên dịch trong ngữ cảnh đúng. – Casper
@Casper khi câu trả lời là "sử dụng chuỗi eval thay vì khối eval", nó thường là thời gian để tìm kiếm một câu trả lời tốt hơn. Chuỗi eval là nguy hiểm và mong manh, đôi khi đó là những gì bạn cần, nhưng tôi ước tính hơn 95% thời gian tôi thấy nó được sử dụng có một hình thức ít nguy hiểm có sẵn. – dbenhur