Anehnya, semua 10 jawaban di sini mengatakan hal yang sama. '::' adalah operator resolusi namespace, dan ya itu benar. Tetapi ada satu gotcha yang harus Anda sadari tentang operator resolusi namespace ketika datang ke algoritma pencarian konstan . Sebagai Matz menggambarkan dalam bukunya, 'Bahasa Pemrograman Ruby', pencarian konstan memiliki beberapa langkah. Pertama, ia mencari konstanta dalam lingkup leksikal di mana konstanta direferensikan. Jika tidak menemukan konstanta dalam lingkup leksikal, maka ia akan mencari hierarki warisan . Karena algoritma pencarian konstan ini, di bawah ini kami mendapatkan hasil yang diharapkan:
module A
module B
PI = 3.14
module C
class E
PI = 3.15
end
class F < E
def get_pi
puts PI
end
end
end
end
end
f = A::B::C::F.new
f.get_pi
> 3.14
Sementara F mewarisi dari E, modul B berada dalam ruang lingkup leksikal F. Akibatnya, instance F akan merujuk ke PI konstan yang didefinisikan dalam modul B. Sekarang jika modul B tidak mendefinisikan PI, maka instance F akan merujuk ke PI konstan didefinisikan dalam superclass E.
Tetapi bagaimana jika kita menggunakan modul '::' daripada bersarang? Apakah kita akan mendapatkan hasil yang sama? Tidak!
Dengan menggunakan operator resolusi namespace ketika mendefinisikan modul bersarang, modul dan kelas bersarang tidak lagi dalam lingkup leksikal dari modul luar mereka. Seperti yang Anda lihat di bawah, PI yang didefinisikan dalam A :: B tidak dalam lingkup leksikal A :: B :: C :: D dan dengan demikian kita mendapatkan konstanta yang tidak diinisialisasi ketika mencoba merujuk ke PI dalam metode instance get_pi:
module A
end
module A::B
PI = 3.14
end
module A::B::C
class D
def get_pi
puts PI
end
end
end
d = A::B::C::D.new
d.get_pi
NameError: uninitialized constant A::B::C::D::PI
Did you mean? A::B::PI