2011-11-04 27 views
12

Tôi đang cố gắng viết một chương trình tự động định nghĩa các lớp ruby ​​dựa trên cấu hình đọc từ một tệp. Tôi biết tôi có thể sử dụng Class.new để làm điều này. Dưới đây là một chương trình ví dụ:Lớp động Ruby. Cách khắc phục "cảnh báo: truy cập biến lớp từ toplevel"

x = [1,2,3] 

Test = Class.new do 
    @@mylist = x 

    def foo 
    puts @@mylist 
    end 
end 

Test.new.foo 

Khi tôi chạy này tôi nhận được kết quả như sau (chạy với ruby ​​1.9.3p0):

c:/utils/test.rb:4: warning: class variable access from toplevel 
c:/utils/test.rb:7: warning: class variable access from toplevel 
1 
2 
3

Có ai biết những gì gây ra những cảnh báo này và làm thế nào tôi có thể thoát khỏi của họ?

tôi đã cố gắng thay thế các dòng tjhat không

@@mylist = x

với điều này

class_variable_set(:@@mylist, x)

Nhưng khi tôi làm điều đó tôi nhận được lỗi này thay vì:

c:/utils/test.rb:7: warning: class variable access from toplevel 
c:/utils/test.rb:7:in `foo': uninitialized class variable @@mylist in Object (NameError) 
     from c:/utils/test.rb:11:in `'

Cảm ơn trước !

Trả lời

7

Chỉ cần để xóa cảnh báo này, bạn nên sử dụng class_variable_set phương pháp:

x = [1,2,3] 

Test = Class.new do 
    class_variable_set(:@@mylist, x) 

    def foo 
    puts @@mylist 
    end 
end 
+0

Điều đó mang lại cho tôi một lỗi không may. Tôi đã cập nhật câu hỏi gốc với các chi tiết. –

+0

Hmm - chỉ Ruby 1.9.2 có thể cung cấp cho bạn một cảnh báo như vậy về 'truy cập biến lớp từ toplevel'. Nhưng 'NameError' với thông điệp' uninitialized class variable' chỉ có thể xuất phát từ Ruby 1.8 vì phương thức 'class_variable_set' là riêng tư trong phiên bản này. Có lẽ đó là câu hỏi ngu ngốc :) nhưng bạn có chắc chắn rằng bạn đang chạy cả hai phiên bản trong cùng một phiên bản ruby? Nếu tôi sử dụng 1.8 với đoạn mã ban đầu của bạn, tôi không có bất kỳ thông điệp cảnh báo nào và nếu tôi sử dụng 1.9 với đoạn mã của tôi, điều đó có vẻ là ok ... – WarHog

+1

Cảm ơn WarHog. Tôi vừa thử mã của bạn trên 1.9.2p290 và nó hoạt động không có lỗi. Nhưng khi tôi chạy nó với 1.9.3p0 tôi nhận được lỗi tôi mô tả ở trên. Tôi sẽ xem xét những điểm mới cho 1.9.3 và xem liệu có điều gì có thể giải thích sự khác biệt về hành vi. –

2

Thay vì xác định "mylist" biến lớp học của bạn trên lớp khi khai báo lớp, bạn có thể khai báo các biến mức lớp trên nó sau này như sau. Hai phương pháp khác nhau được hiển thị. Các công trình trước đây chỉ hoạt động trong 1,9, sau này hoạt động trong cả hai phiên bản, nhưng ít thành ngữ.

x = [1,2,3] 

Test = Class.new do 
    def foo 
    puts @@mylist 
    end 
end 

# ruby 1.9.2 
Test.class_variable_set(:@@mylist, x) 

# ruby 1.8.7 
Test.class_eval { 
    @@mylist = x 
} 

Test.new.foo 
+0

Cảm ơn bạn đã trả lời. Thật không may khi chạy với 1.9.3, phiên bản đầu tiên gây ra lỗi mà tôi đã thấy và phiên bản thứ hai đưa ra những cảnh báo tôi có! Tôi bắt đầu nghi ngờ đây là một sự thay đổi trong hành vi/hồi quy trong ruby ​​1.9.3. –

15

Điều này không làm những gì bạn nghĩ rằng nó đang làm. Vì bạn không tạo lớp học với từ khóa class, biến lớp học của bạn đang được đặt trên Object, không phải là Test. Các tác động của điều này là khá lớn, đó là lý do tại sao Ruby cảnh báo bạn. Biến lớp được chia sẻ giữa tổ tiên và đối tượng thường được kế thừa từ Object.

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