Những điều bạn cần biết về hằng số trong Ruby
Có rất nhiều thứ về hằng số trong Ruby mà bạn có thể nghĩ đến, ví dụ như bạn có thể thay đổi giá trị của 1 hằng số trong Ruby, không giống như các ngôn ngữ khác như C và Java. Chúng ta sẽ khám phá chi tiết hơn trong bài viết này nhé! Định nghĩa hằng số Một hằng số trong Ruby không yêu cầu một ký ...
Có rất nhiều thứ về hằng số trong Ruby mà bạn có thể nghĩ đến, ví dụ như bạn có thể thay đổi giá trị của 1 hằng số trong Ruby, không giống như các ngôn ngữ khác như C và Java. Chúng ta sẽ khám phá chi tiết hơn trong bài viết này nhé! Định nghĩa hằng số Một hằng số trong Ruby không yêu cầu một ký hiệu hay cú pháp đặc biệt gì để khai báo, bạn đơn giản chỉ cần viết hoa chữ cái đầu của tên hằng số. Dưới đây là 1 vài hằng số hợp lệ:
ABC = 1 Goo = 2 Foo = 3
Lưu ý rằng bạn không thể khai báo một hằng số bên trong một phương thức, nếu không bạn sẽ nhận thông báo lỗi như sau:
def the_method ABC = 1 end # "dynamic constant assignment"
Vì vậy, bạn chỉ cần khai báo hằng số ở bên ngoài phương thức, thông thường, chúng ta khai báo hằng số trên cùng của class vì thế chúng có thể được nhìn thấy rõ ràng.
class RubyBlog URL = "blackbytes.info" AUTHOR = "Jesus Castello" end
Sau đó, bạn có thể truy cập các hằng số này bên trong phương thức của class hoặc phương thức của class khác bằng cách sử dụng cú pháp:
p RubyBlog::AUTHOR # "Jesus Castello"
Uninitialized Constant Một lỗi phổ biến mà bạn có thể nhận được là:
puts Foo # "uninitialized constant Foo (NameError)"
Bạn có thể hiểu nhầm lỗi này thành "constant not found Foo". Một điểm quan trọng để hiểu lỗi này đó là các class trong Ruby đều được coi là các hằng số:
Array String Hash
Chúng là các hằng số vì chữ cái đầu của chúng viết hoa. Điều này là quan trọng bởi vì hầu hết lý do bạn nhìn thấy lỗi này là bạn quên khi require một số file hoặc gem cái mà được định nghĩa hằng số. Hoặc có thể bạn chỉ sai lỗi chính tả của tên hằng số. Vì thế hãy để ý các vấn đề này. Hằng số có thể thay đổi Giống như đã đề cập khi giới thiệu, hằng số trong Ruby có thể thay đổi:
ABC = 1 ABC = 2
Nhưng bạn vẫn nhìn thấy message cảnh báo:
2: warning: already initialized constant ABC
Chương trình của bạn vẫn chạy tốt, nhưng bạn nên tránh cách thay đổi này. Không có cách nào để ngăn chặn một hằng số thay đổi bởi vì biến trong Ruby luôn trỏ tới một đối tượng. Cách tốt nhất để làm thế là sử dụng một đối tượng bất biến. Ví dụ:
AUTHOR = "Jesus Castello".freeze AUTHOR << "o" # RuntimeError: can't modify frozen String
Chú ý rằng trong ví dụ trên, bạn vẫn thay đổi cái mà hằng số AUTHOR trỏ tới, điều duy nhất freeze bảo vệ bạn là việc tự nó thay đổi đối tượng. Constant Methods Có một số phương thức được dùng để làm việc với hằng số:
Phương thức | Mô tả |
---|---|
constants | Trả về một mảng các ký hiệu đại diện cho các hằng số được định nghĩa trong class |
const_get | Trả về giá trị của hằng số. Tham số là một ký hiệu hoặc một string |
const_set | Thiết lập giá trị cho một hằng số. sử dụng 2 tham số: tên hằng số như một ký hiệu và giá trị của hằng số |
const_missing | Giống phương thức method_missing nhưng sử dụng cho hằng số |
const_defined? | Trả về true nếu hằng số được gọi đã được định nghĩa |
remove_const | Loại bỏ một hằng số |
private_constant | Làm cho một hằng số private vì thế nó không thể được truy cập bên ngoài class với cú pháp Class::ABC |
Ví dụ:
module Food class Bacon; end class Chocolate; end end puts "Classes defined inside #{Food}:" puts Food.constants
Bạn cũng có thể sử dụng chuỗi như Array và nhận về lớp thực tế:
array_class = Object.const_get("Array")
Trong Rails, có phương thức constantize thực hiện việc const_get cho bạn, nhưng nó không thực hiện bất kỳ một kiểm tra bảo mật nào. Ruby Constant Scope Khi bạn tạo một hằng số bên ngoài một class nào đó, hằng số này sẽ có thể dùng ở bất kỳ nơi nào. Hằng số cũng có thể sử dụng trong các lớp con:
class A FOO = 1 end class B < A def foo puts FOO end end B.constants # [:FOO]
Hằng số được định nghĩa bên ngoài một nested module hoặc lớp cũng có thể dùng bên trong các class lồng nhau.
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 Mixing Các hằng số từ các module cũng có thể dùng:
module Mixin A = 123 end class Product include Mixin puts A end # 123
Lưu ý rằng điều này hoạt động khi include các module, nó sẽ không hoạt động nếu bạn extend nó. Ví dụ:
class Product extend Mixin puts A end # uninitialized constant Product::A
Ngoài ra, khi bạn sử dụng một phương thức được định nghĩa trong phương thức included, nó sẽ sử dụng hằng số được định nghĩa trong module đó, cho dù nếu có cùng một hằng số được định nghĩa trong class hiện tại.
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
Module Nesting Dưới đây là một ví dụ nữa về nested classes (giống như các module).
class A FOO = 1 end class A::B class C puts FOO end end # NameError: uninitialized constant A::B::C::FOO
Chú ý ký hiệuA :: B ở đây sử dụng như một phím tắt. Nhưng vấn đề là class C sẽ không có quyền truy cập vào trực tiếp FOO. Vì lý do đó, bạn có thể sẽ muốn sử dụng cách sau:
class A FOO = 1 end class A class B class C puts FOO end end end # 1
Trong ví dụ đầu tiên bạn vẫn có thể dùng :: :: FOO để truy cập hằng số, nhưng nếu tên lớp thay đổi thì bạn sẽ gặp lỗi.
Cú pháp :: A :: FOO này hoạt động vì nó làm cho Ruby tìm trong top-level của scope, nơi các hằng số được định nghĩa giống như Array & String. Kết luận Như vậy, bạn đã học về hằng số trong Ruby, một loại biến có một số hành vi thú vị. Bạn có thể thay đổi giá trị của một hằng số nhưng nó sẽ tạo ra một cảnh báo. Bạn cũng học được rằng tên lớp là các hằng số và rằng bạn nên tránh sử dụng const_get với các input nhập vào của người dùng. Cảm ơn các bạn đã đọc bài viết!!!