Tôi đã quên rằng có là một khái niệm "biến thể hiện lớp" trong Ruby. Trong mọi trường hợp, vấn đề của OP có vẻ khó hiểu, và không thực sự được giải quyết trong bất kỳ câu trả lời nào trước đây, ngoại trừ một gợi ý trong câu trả lời của kch: đó là một vấn đề về phạm vi. (Được thêm vào chỉnh sửa: Trên thực tế, câu trả lời của sris không giải quyết vấn đề này vào lúc nào, nhưng tôi sẽ cho phép câu trả lời này đứng yên, vì tôi nghĩ mã ví dụ có thể hữu ích để hiểu vấn đề.)
In a Lớp Ruby, tên biến số bắt đầu bằng @
có thể tham chiếu đến một trong số hai biến số: hoặc là biến thể hiện hoặc đến một biến thể hiện lớp , tùy thuộc vào vị trí của lớp. Đây là một hình ảnh khá tinh tế.
Ví dụ sẽ làm rõ điểm. Dưới đây là một chút lớp của Ruby thử nghiệm (tất cả các mã thử nghiệm trong IRB):
class T
@@class_variable = "BBQ"
@class_instance_variable_1 = "WTF"
@class_instance_variable_2 = "LOL"
def self.class_method
puts "@@class_variable == #{@@class_variable || 'nil'}"
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
def initialize
@instance_variable = "omg"
# The following line does not assign a value to the class instance variable,
# but actually declares an instance variable withthe same name!
@class_instance_variable_1 = "wtf"
puts "@@class_variable == #{@@class_variable || 'nil'}"
# The following two lines do not refer to the class instance variables,
# but to the instance variables with the same names.
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
def instance_method
puts "@@class_variable == #{@@class_variable || 'nil'}"
# The following two lines do not refer to the class instance variables,
# but to the instance variables with the same names.
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
end
tôi đặt tên các biến theo những gì tôi nghĩ họ, dù rằng hóa ra không phải luôn luôn là trường hợp:
irb> T.class_method
@@class_variable == BBQ
@class_instance_variable_1 == WTF # the value of the class instance variable
@class_instance_variable_2 == LOL # the value of the class instance variable
@instance_variable == nil # does not exist in the class scope
=> nil
irb> t = T.new
@@class_variable == BBQ
@class_instance_variable_1 == wtf # the value of the instance variable
@class_instance_variable_2 == nil # the value of the instance variable
@instance_variable == omg
=> #<T:0x000000015059f0 @instance_variable="omg", @class_instance_variable_1="wtf">
irb> t.instance_method
@@class_variable == BBQ
@class_instance_variable_1 == wtf # the value of the instance variable
@class_instance_variable_2 == nil # the value of the instance variable
@instance_variable == omg
=> nil
irb> T.class_method
@@class_variable == BBQ
@class_instance_variable_1 == WTF # the value of the class instance variable
@class_instance_variable_2 == LOL # the value of the class instance variable
@instance_variable == nil # does not exist in the class scope
=> nil
@@class_variable
và @instance_variable
luôn hoạt động như bạn mong muốn: giá trị cũ được xác định ở cấp lớp và được tham chiếu trong phương thức lớp hoặc phương pháp thể hiện, nó giữ giá trị được gán cho nó ở trên cùng. Cái sau chỉ nhận được một giá trị trong một đối tượng của lớp T
, vì vậy trong một phương thức lớp, nó chỉ một biến không xác định có giá trị là nil
.
Phương pháp lớp có tên là class_method
xuất ra các giá trị @@class_variable
và hai số @class_instance_variable
s như mong đợi, tức là, như được khởi tạo ở đầu lớp. Tuy nhiên, trong các phương pháp ví dụ initialize
và instance_method
, khác nhau biến cùng tên được truy cập, nghĩa là, biến mẫu, không phải biến thể hiện lớp.
Bạn có thể thấy rằng sự phân công trong phương pháp initialize
không ảnh hưởng đến cá thể lớp biến @class_instance_variable_1
, vì cuộc gọi sau này của class_method
kết quả đầu ra giá trị cũ của nó, "WTF"
. Thay vào đó, phương pháp initialize
đã khai báo một biến mẫu mới, một trong đó là cũng có tên (misleadingly) @class_instance_variable_1
. Giá trị được gán cho nó, "wtf"
, được xuất theo phương thức initialize
và instance_method
.
Biến @class_instance_variable_2
trong mã ví dụ là tương đương với biến @hello
trong vấn đề ban đầu: nó khai báo và khởi tạo như là một biến lớp Chẳng hạn, nhưng khi một phương pháp dụ đề cập đến một biến của tên đó, nó thực sự thấy một ví dụ biến có cùng tên - một trong số đó chưa bao giờ được khai báo, vì vậy giá trị của nó là không.
Bạn nói rằng "chúng sinh ra trong cuộc sống lần đầu tiên chúng được chỉ định", nhưng OP cho thấy một ví dụ với sự phân công rõ ràng sớm hơn trong ví dụ của bạn, và vấn đề có kinh nghiệm là biến đã không nảy sinh vào cuộc sống. – kaleidic
@kaleidic Chính xác. Tôi hơi bối rối về số lượng upvotes trong câu trả lời này không giải quyết được câu hỏi của OP. Trong thực tế, biến cá thể lớp '@ hello' * làm * spring vào cuộc sống trên hàng 2 của mã ví dụ, nhưng vấn đề là không phải là biến mà hàng 4 đề cập đến. Xem câu trả lời của tôi dưới đây để biết thêm chi tiết. –
Xin lỗi, bạn thực sự trả lời câu hỏi ở phần cuối, điều mà tôi đã bỏ lỡ khi đọc lần đầu tiên. –