2010-09-27 56 views

Trả lời

132

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 
+0

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

+0

@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? –

59

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ế.

+0

+1 để phác thảo các lớp đó là các thể hiện của 'Class' – mikezter

+1

+1 Giải thích siêu! Đây là điều mà mọi lập trình viên mới sử dụng để Ruby nên tiêu hóa. – TomZ

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