น่าแปลกใจที่ทั้ง 10 คำตอบที่นี่พูดในสิ่งเดียวกัน '::' เป็นตัวดำเนินการแก้ไขเนมสเปซและใช่เป็นจริง แต่มีหนึ่ง gotcha ที่คุณต้องรู้เกี่ยวกับผู้ประกอบการที่มีความละเอียด namespace เมื่อมันมาถึงขั้นตอนวิธีการค้นหาอย่างต่อเนื่อง เมื่อ Matz แยกตัวในหนังสือของเขา 'The Ruby Programming Language' การค้นหาคงที่มีหลายขั้นตอน ก่อนอื่นมันจะค้นหาค่าคงที่ในขอบเขตของคำซึ่งอ้างอิงค่าคงที่ ถ้ามันไม่ได้หาอย่างต่อเนื่องภายในขอบเขตคำศัพท์มันก็จะค้นหาลำดับชั้นมรดก เนื่องจากอัลกอริทึมการค้นหาแบบคงที่ด้านล่างเราจึงได้ผลลัพธ์ที่ต้องการ:
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
ในขณะที่ F สืบทอดมาจาก E โมดูล B จะอยู่ภายในขอบเขตศัพท์ของ F ดังนั้นอินสแตนซ์ F จะอ้างถึงค่าคงที่ PI ที่กำหนดไว้ในโมดูล B ตอนนี้ถ้าโมดูล B ไม่ได้กำหนด PI ดังนั้นอินสแตนซ์ F จะอ้างถึง PI ค่าคงที่ที่กำหนดใน superclass E
แต่ถ้าเราใช้ '::' แทนการซ้อนโมดูลล่ะ เราจะได้ผลเหมือนกันไหม? No!
โดยใช้โอเปอเรเตอร์การแก้ปัญหาเนมสเปซเมื่อกำหนดโมดูลที่ซ้อนกันโมดูลและคลาสที่ซ้อนกันจะไม่อยู่ในขอบเขตศัพท์ของโมดูลภายนอก ดังที่คุณเห็นด้านล่าง PI ที่กำหนดใน A :: B ไม่อยู่ในขอบเขตศัพท์ของ A :: B :: C :: D และทำให้เราได้ค่าคงตัวที่ไม่กำหนดเมื่อพยายามอ้างถึง PI ในเมธอดอินสแตนซ์ 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