Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ทุกสิ่งที่คุณจำเป็นต้องรู้เกี่ยวกับค่าคงที่ของ Ruby

ค่าคงที่ใน Ruby คืออะไร

ค่าคงที่คือตัวแปรประเภทหนึ่งที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่เสมอ กำหนดได้เฉพาะ ภายนอก ของเมธอด เว้นแต่คุณจะใช้ metaprogramming

ค่าคงที่ใช้สำหรับค่าที่ไม่ควรเปลี่ยนแปลง แต่ Ruby ไม่ได้ป้องกันคุณจากการเปลี่ยนแปลง

หน้าตาเป็นแบบนี้ :

FRUIT = "orange"

ตอนนี้ :

เนื่องจากค่าคงที่เป็นหัวข้อสำคัญ เราจะมาดูรายละเอียดในบทความนี้!

วิธีการกำหนดค่าคงที่

ค่าคงที่ไม่ต้องการสัญลักษณ์หรือไวยากรณ์พิเศษใด ๆ เพื่อประกาศ คุณเพียงแค่ต้องทำให้ตัวอักษรตัวแรกเป็นตัวพิมพ์ใหญ่

ต่อไปนี้คือค่าคงที่ที่ถูกต้อง :

ABC = 1
Goo = 2
Foo = 3

สังเกตว่าคุณไม่สามารถกำหนดค่าคงที่ภายในเมธอดได้

คุณจะได้รับข้อความแสดงข้อผิดพลาดที่คลุมเครือนี้ :

def the_method
  ABC = 1
end

# "dynamic constant assignment"

ดังนั้น เพียงแค่กำหนดค่าคงที่ของคุณภายนอกเมธอด โดยปกติเราต้องการให้มีคำจำกัดความคงที่ที่ด้านบนสุดของคลาสของคุณเพื่อให้มองเห็นได้ชัดเจน

class RubyBlog
  URL    = "rubyguides.com"
  AUTHOR = "Jesus Castello"
end

จากนั้นคุณสามารถเข้าถึงค่าคงที่เหล่านี้ได้ภายในเมธอดของคลาสหรือภายนอกคลาสโดยใช้ไวยากรณ์ต่อไปนี้:

p RubyBlog::AUTHOR

# "Jesus Castello"

เราจะพูดถึงขอบเขตของค่าคงที่เพิ่มเติมในโพสต์นี้ โปรดคอยติดตาม!

ข้อผิดพลาดคงที่ที่ไม่ได้กำหนดค่าเริ่มต้น

ข้อผิดพลาดทั่วไปที่คุณอาจได้รับคือ:

puts Foo
# "uninitialized constant Foo (NameError)"

ฉันต้องการให้คุณแปลข้อผิดพลาดนี้ในใจว่า “ไม่พบค่าคงที่”

จุดสำคัญอย่างหนึ่งในการทำความเข้าใจข้อผิดพลาดนี้คือคลาส Ruby เป็นค่าคงที่

ตัวอย่าง :

Array
String
Hash

เป็นค่าคงที่เนื่องจากตัวอักษรตัวแรกเป็นตัวพิมพ์ใหญ่

เมื่อคุณกำหนดคลาส สิ่งที่คุณทำจริงๆ คือการสร้าง Class วัตถุซึ่งถูกกำหนดให้เป็นค่าคงที่

ค่าคงที่กลายเป็นชื่อคลาส

เหตุใดจึงสำคัญ

เนื่องจากสาเหตุที่เป็นไปได้มากที่สุดที่คุณเห็นข้อผิดพลาด "ค่าคงที่ที่ไม่ได้กำหนดค่าเริ่มต้น" ก็คือคุณลืม require ไฟล์หรืออัญมณีที่กำหนดค่าคงที่

หรือบางทีคุณอาจสะกดชื่อค่าคงที่ผิด

ดังนั้นจงจับตาดูให้ดี

ค่าคงที่เปลี่ยนได้

ดังที่ได้กล่าวไว้ในบทนำ ค่าคงที่ของ Ruby สามารถเปลี่ยนแปลงได้

ตัวอย่าง :

ABC = 1
ABC = 2

แต่คุณจะเห็นข้อความเตือนนี้:

2: warning: already initialized constant ABC

โปรแกรมของคุณยังคงทำงานได้ดี แต่คุณต้องการหลีกเลี่ยงสิ่งนี้

ไม่มีทางที่จะป้องกันไม่ให้ค่าคงที่เปลี่ยนแปลงได้ เนื่องจากตัวแปรใน Ruby ไม่ใช่คอนเทนเนอร์ แต่เป็นเพียงตัวชี้ไปยังวัตถุ

หรือฉลากได้ตามต้องการ

สิ่งที่ดีที่สุดที่คุณสามารถทำได้คือการใช้วัตถุที่ไม่เปลี่ยนรูป

ตัวอย่าง :

AUTHOR = "Jesus Castello".freeze

AUTHOR << "o"
# RuntimeError: can't modify frozen String

บทความที่เกี่ยวข้อง :การกลายพันธุ์ของทับทิม &วิธีการแช่แข็ง

ในตัวอย่างนี้ คุณยังสามารถเปลี่ยนสิ่งที่ AUTHOR ค่าคงที่ชี้ไปที่สิ่งเดียวที่ หยุด ปกป้องคุณจากการเปลี่ยนแปลงของวัตถุเอง

วิธีการคงที่

มีวิธีการสองสามวิธีที่ใช้กับค่าคงที่:

วิธีการ คำอธิบาย
ค่าคงที่ ส่งคืนอาร์เรย์ของสัญลักษณ์ที่แสดงค่าคงที่ที่กำหนดไว้ในคลาส
const_get คืนค่าสำหรับค่าคงที่ ใช้สัญลักษณ์หรือสตริงเป็นพารามิเตอร์
const_set ตั้งค่าสำหรับค่าคงที่ รับสองพารามิเตอร์:ชื่อคงที่เป็นสัญลักษณ์ &ค่าคงที่
const_missing เหมือนกับ method_missing แต่สำหรับค่าคงที่
const_defined? คืนค่า จริง หากค่าคงที่ที่กำหนด (เป็นสัญลักษณ์) ถูกกำหนดไว้แล้ว
remove_const ลบค่าคงที่
private_constant ทำให้ค่าคงที่ส่วนตัวไม่สามารถเข้าถึงได้นอกชั้นเรียนด้วย Class::ABC ไวยากรณ์

มีเทคนิค metaprogramming สองสามอย่างที่คุณสามารถทำได้โดยใช้วิธีการเหล่านี้

ตัวอย่าง :

module Food
  class Bacon; end
  class Chocolate; end
end

puts "Classes defined inside #{Food}:"

puts Food.constants

คุณสามารถใช้สตริงเช่น "อาร์เรย์" และรับคลาสจริง:

array_class = Object.const_get("Array")

แต่ระวังตัวด้วยเพราะผู้ใช้สามารถฉีดโค้ดได้หากสตริงนั้นมาจาก params หรือรูปแบบอื่นๆ ของการป้อนข้อมูลของผู้ใช้

ใน Rails มีวิธีทำให้คงที่ซึ่งโดยทั่วไปแล้วจะทำ const_get สำหรับคุณ แต่โปรดทราบว่าไม่มีการตรวจสอบความปลอดภัยใดๆ

สูตรโกง

ทุกสิ่งที่คุณจำเป็นต้องรู้เกี่ยวกับค่าคงที่ของ Ruby

ขอบเขตทับทิมคงที่

เมื่อคุณสร้างค่าคงที่นอกคลาสใดๆ ที่ระดับบนสุดของโค้ดของคุณ ค่าคงที่นั้นจะสามารถใช้ได้ทุกที่

ค่าคงที่ยังมีอยู่ในชั้นเรียนย่อย

class A
  FOO = 1
end

class B < A
  def foo
    puts FOO
  end
end

B.constants

# [:FOO]

ค่าคงที่ที่กำหนดนอกโมดูลหรือคลาสที่ซ้อนกันนั้นยังมีอยู่ในคลาสที่ซ้อนกันด้วย

module Food
  STORE_ADDRESS = "The moon"

  class Bacon
    def foo; puts STORE_ADDRESS; end
  end
end

fb = Food::Bacon.new
fb.foo

# "The moon"

การผสมโมดูล

ค่าคงที่จากโมดูลแบบผสมก็มีให้เช่นกัน:

module Mixin
  A = 123
end

class Product
  include Mixin

  puts A
end

# 123

สังเกตว่าสิ่งนี้ใช้ได้เมื่อรวมโมดูลด้วย มันจะไม่ทำงานหากคุณกำลังขยายโมดูล

ตัวอย่าง :

class Product
  extend Mixin

  puts A
end

#  uninitialized constant Product::A

เช่นกัน :

เมื่อคุณใช้เมธอดที่รวมมาจากโมดูล Ruby จะค้นหาค่าคงที่เริ่มต้นจากตำแหน่งที่กำหนดเมธอดนั้น

ตัวอย่าง :

module Parent
  def print_value
    VALUE
  end
end

class Child
  include Parent

  VALUE = 1
end

# Works
p Child::VALUE

# uninitialized constant Parent::VALUE
p Child.new.print_value

สิ่งที่ควรทราบ!

การซ้อนโมดูล

ฉันต้องการแสดงตัวอย่างเพิ่มเติมกับคลาสที่ซ้อนกัน (เหมือนกันสำหรับโมดูล)

class A
  FOO = 1
end

class A::B
  class C
    puts FOO
  end
end

สังเกต A::B สัญกรณ์ที่นี่ซึ่งเราพยายามใช้เป็นทางลัด แต่ปัญหาคือคลาสนั้น C จะไม่สามารถเข้าถึง FOO โดยตรง

ด้วยเหตุผลดังกล่าว คุณจึงต้องการยึดติดประเภทนี้:

class A
  FOO = 1
end

class A
  class B
    class C
      puts FOO
    end
  end
end

ในตัวอย่างแรก คุณยังสามารถทำ ::A::FOO เพื่อเข้าถึงค่าคงที่ แต่ถ้าชื่อคลาสเปลี่ยนไป คุณจะได้รับข้อผิดพลาด

::A::FOOนี้ ::A::FOO ไวยากรณ์ใช้งานได้เพราะมันบอกให้ Ruby ดูในขอบเขตระดับบนสุด โดยที่ค่าคงที่เช่น Array &สตริง ถูกกำหนดไว้แล้ว

วิดีโอ

สรุป

คุณได้เรียนรู้เกี่ยวกับค่าคงที่ Ruby ซึ่งเป็นตัวแปรประเภทหนึ่งที่มีพฤติกรรมที่น่าสนใจ คุณสามารถเปลี่ยนค่าของค่าคงที่ได้ แต่จะพิมพ์คำเตือน

คุณยังได้เรียนรู้ว่าชื่อคลาสเป็นค่าคงที่ &คุณควรหลีกเลี่ยง const_get ด้วยการป้อนข้อมูลของผู้ใช้

หากคุณชอบโพสต์นี้ อย่าลืมแชร์ เพื่อให้คนอื่นเข้าใจการทำงานของค่าคงที่มากขึ้น