Bất cứ ai có thể cho tôi biết về sự khác biệt giữa biến lớp và biến thể hiện lớp?Sự khác nhau giữa các biến lớp và biến thể hiện lớp?
Trả lời
Biến lớp (@@
) được chia sẻ giữa lớp và tất cả các hậu duệ của lớp đó. Biến thể hiện lớp (@
) không được chia sẻ bởi con cháu của lớp.
biến Lớp (@@
)
Hãy có một Foo lớp với một lớp biến @@i
, và các phụ kiện cho việc đọc và viết @@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
Và một lớp có nguồn gốc:
class Bar < Foo
end
Chúng ta thấy rằng Foo và Bar có cùng giá trị cho @@i
:
p Foo.i # => 1
p Bar.i # => 1
Và thay đổi @@i
trong một thay đổi nó trong cả hai:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
dụ Lớp biến (@
)
Hãy tạo một lớp đơn giản với một thể hiện đẳng cấp và riable @i
và các phụ kiện cho việc đọc và viết @i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Và một lớp có nguồn gốc:
class Bar < Foo
end
Chúng tôi nhận thấy rằng mặc dù Bar thừa hưởng các phụ kiện cho @i
, nó không kế thừa @i
bản thân:
p Foo.i # => 1
p Bar.i # => nil
Chúng tôi có thể đặt Bar @i
mà không ảnh hưởng đến sốcủa Foo:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
Trước tiên, bạn cũng phải hiểu rằng các lớp là trường hợp - trường hợp của lớp Class
.
Khi bạn hiểu điều đó, bạn có thể hiểu rằng một lớp có thể có các biến mẫu được liên kết với nó giống như một đối tượng thông thường (đọc: không phải lớp).
Hello = Class.new
# setting an instance variable on the Hello class
Hello.instance_variable_set(:@var, "good morning!")
# getting an instance variable on the Hello class
Hello.instance_variable_get(:@var) #=> "good morning!"
Lưu ý rằng một biến Ví dụ trên Hello
là hoàn toàn không liên quan đến và khác biệt từ một biến Ví dụ về một thể hiện của Hello
hello = Hello.new
# setting an instance variable on an instance of Hello
hello.instance_variable_set(:@var, :"bad evening!")
# getting an instance variable on an instance of Hello
hello.instance_variable_get(:@var) #=> "bad evening!")
# see that it's distinct from @var on Hello
Hello.instance_variable_get(:@var) #=> "good morning!"
Một lớp biến mặt khác là một loại của sự kết hợp của hai trường hợp trên, vì nó có thể truy cập trên Hello
chính nó và các trường hợp của nó, cũng như trên các lớp con của Hello
và các phiên bản của chúng:
HelloChild = Class.new(Hello)
Hello.class_variable_set(:@@class_var, "strange day!")
hello = Hello.new
hello_child = HelloChild.new
Hello.class_variable_get(:@@class_var) #=> "strange day!"
HelloChild.class_variable_get(:@@class_var) #=> "strange day!"
hello.singleton_class.class_variable_get(:@@class_var) #=> "strange day!"
hello_child.singleton_class.class_variable_get(:@@class_Var) #=> "strange day!"
Nhiều người nói để tránh class variables
vì hành vi lạ ở trên và khuyên bạn nên sử dụng class instance variables
thay thế.
Tại sao trả về các biến mẫu bằng cách sử dụng các phương thức lớp? Bạn có thường xuyên gặp phải tình huống này không? – sekmo
@sekmo Những người truy cập trong các ví dụ này trả về biến thể _class __, thuộc về lớp, hoặc biến _class_, thuộc về phân cấp lớp. Chúng không trả về các biến _instance đơn giản mà thuộc về các cá thể của lớp. Thuật ngữ "biến thể hiện", "biến thể cá thể lớp" và "biến lớp" khá khó hiểu, đúng không? –