Adakah yang bisa memberi tahu saya tentang perbedaan antara variabel kelas dan variabel contoh kelas?
Jawaban:
Variabel kelas ( @@
) dibagikan di antara kelas dan semua turunannya. Variabel instance kelas ( @
) tidak dibagikan oleh turunan kelas.
Variabel kelas ( @@
)
Mari kita memiliki kelas Foo dengan variabel kelas @@i
, dan pengakses untuk membaca dan menulis @@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
Dan kelas turunan:
class Bar < Foo
end
Kami melihat bahwa Foo dan Bar memiliki nilai yang sama untuk @@i
:
p Foo.i # => 1
p Bar.i # => 1
Dan mengubah @@i
satu perubahan di keduanya:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Variabel instance kelas ( @
)
Mari buat kelas sederhana dengan variabel instance kelas @i
dan aksesor untuk membaca dan menulis @i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Dan kelas turunan:
class Bar < Foo
end
Kita melihat bahwa meskipun Bar mewarisi aksesornya @i
, ia tidak mewarisi @i
dirinya sendiri:
p Foo.i # => 1
p Bar.i # => nil
Kita dapat mengatur Bar @i
tanpa mempengaruhi Foo @i
:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
Pertama, Anda harus memahami bahwa kelas juga merupakan instance - instance Class
kelas.
Setelah Anda memahaminya, Anda dapat memahami bahwa kelas dapat memiliki variabel instan yang terkait dengannya seperti halnya objek biasa (baca: non-kelas).
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!"
Perhatikan bahwa variabel contoh pada Hello
sama sekali tidak berhubungan dengan dan berbeda dari variabel contoh pada sebuah contoh dariHello
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!"
Sebuah variabel kelas di sisi lain adalah semacam kombinasi di atas dua, karena dapat diakses pada Hello
dirinya sendiri dan contoh nya, serta pada subclass dari Hello
dan contoh mereka:
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!"
Banyak orang mengatakan untuk menghindari class variables
karena perilaku aneh di atas, dan merekomendasikan penggunaan class instance variables
sebagai gantinya.
Juga saya ingin menambahkan bahwa Anda bisa mendapatkan akses ke variabel kelas ( @@
) dari setiap contoh kelas
class Foo
def set_name
@@name = 'Nik'
end
def get_name
@@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => Nik
Tetapi Anda tidak dapat melakukan hal yang sama untuk variabel instance kelas ( @
)
class Foo
def set_name
@name = 'Nik'
end
def get_name
@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => nil
Foo.i
, tetapi bagaimana Anda dapat melakukan hal yang sama untuk setiap contoh dari kelas ini Foo.new.i
?
#class
. Saya pribadi berpikir #class
penggunaan ketika dipanggil apa pun kecuali self
bau kode sekalipun. Anda bahkan dapat melangkah lebih jauh dan mengimplementasikan pengakses instance i
dan i=
delegasi itu ke #class
padanannya, dalam hal ini Anda dapat melakukannya Foo.new.i
. Saya tidak menyarankan melakukan itu karena itu membuat antarmuka yang membingungkan, menyarankan Anda memodifikasi anggota objek.