Computer >> Máy Tính >  >> Lập trình >> Ruby

Mọi thứ bạn cần biết về các hằng số Ruby

Hằng số trong Ruby là gì?

Hằng là một loại biến luôn bắt đầu bằng một chữ cái viết hoa. Chúng chỉ có thể được xác định bên ngoài trong số các phương thức, trừ khi bạn sử dụng lập trình siêu hình.

Hằng số được sử dụng cho các giá trị không được phép thay đổi, nhưng Ruby không ngăn bạn thay đổi chúng.

Chúng trông như thế này :

FRUIT = "orange"

Bây giờ :

Bởi vì hằng số là một chủ đề quan trọng, chúng tôi sẽ khám phá chúng một cách chi tiết trong bài viết này!

Cách xác định hằng số

Một hằng số không yêu cầu bất kỳ ký hiệu hoặc cú pháp đặc biệt nào để khai báo. Bạn chỉ cần đặt chữ cái đầu tiên thành chữ hoa.

Sau đây là các hằng số hợp lệ :

ABC = 1
Goo = 2
Foo = 3

Lưu ý rằng bạn không thể xác định các hằng số bên trong một phương thức.

Bạn sẽ nhận được thông báo lỗi khó hiểu này :

def the_method
  ABC = 1
end

# "dynamic constant assignment"

Vì vậy, chỉ cần xác định hằng số của bạn bên ngoài các phương thức, thông thường, chúng tôi muốn có các định nghĩa hằng số ở đầu lớp của bạn để chúng được hiển thị rõ ràng.

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

Sau đó, bạn có thể truy cập các hằng số này bên trong các phương thức của lớp hoặc bên ngoài lớp bằng cú pháp sau:

p RubyBlog::AUTHOR

# "Jesus Castello"

Chúng ta sẽ nói thêm một chút về phạm vi của hằng số ở phần sau trong bài đăng này, vì vậy hãy chú ý theo dõi!

Lỗi liên tục chưa được khởi tạo

Một lỗi phổ biến mà bạn có thể gặp phải là:

puts Foo
# "uninitialized constant Foo (NameError)"

Tôi muốn bạn dịch lỗi này thành "hằng số không tìm thấy".

Một điểm quan trọng để hiểu lỗi này là các lớp Ruby là hằng số.

Ví dụ :

Array
String
Hash

Chúng là hằng số vì chữ cái đầu tiên là chữ hoa.

Khi bạn xác định một lớp, những gì bạn thực sự đang làm là tạo một Class đối tượng, được gán cho một hằng số.

Hằng số trở thành tên lớp.

Tại sao điều này lại quan trọng?

Bởi vì lý do rất có thể khiến bạn gặp lỗi "hằng số chưa được khởi tạo" là bạn quên require một tệp hoặc đá quý xác định hằng số.

Hoặc có thể bạn chỉ viết sai chính tả tên của hằng số.

Vì vậy, hãy để mắt đến điều đó.

Các hằng số có thể thay đổi

Giống như tôi đã đề cập trong phần giới thiệu, các hằng số Ruby có thể thay đổi.

Ví dụ :

ABC = 1
ABC = 2

Nhưng bạn sẽ thấy thông báo cảnh báo này:

2: warning: already initialized constant ABC

Chương trình của bạn sẽ vẫn hoạt động tốt, nhưng bạn muốn tránh điều này.

Không có cách nào để ngăn một hằng số thay đổi vì các biến trong Ruby không phải là vùng chứa, chúng chỉ đơn giản là con trỏ đến các đối tượng.

Hoặc nhãn, nếu bạn thích.

Điều tốt nhất bạn có thể làm là sử dụng các đối tượng không thể thay đổi.

Ví dụ :

AUTHOR = "Jesus Castello".freeze

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

Bài viết có liên quan :Khả năng thay đổi của Ruby và phương pháp đóng băng.

Trong ví dụ này, bạn vẫn có thể thay đổi những gì AUTHOR hằng số đang trỏ đến, điều duy nhất freeze bảo vệ bạn khỏi việc thay đổi chính đối tượng.

Phương thức không đổi

Có một số phương pháp dành riêng để làm việc với hằng số:

Phương pháp Mô tả
hằng số Trả về một mảng ký hiệu đại diện cho các hằng số được xác định trong một lớp
const_get Trả về giá trị cho một hằng số. Lấy biểu tượng hoặc chuỗi làm tham số
const_set Đặt giá trị cho một hằng số. Lấy hai tham số:tên hằng làm ký hiệu và giá trị không đổi
const_missing Giống với method_missing nhưng đối với hằng số
const_defined? Trả về true nếu một hằng số nhất định (dưới dạng ký hiệu) đã được xác định
remove_const Xóa một hằng số
private_constant Đặt một hằng số riêng tư để nó không thể được truy cập bên ngoài lớp với Class::ABC cú pháp

Có một số thủ thuật lập trình siêu hình mà bạn có thể thực hiện bằng các phương pháp này.

Ví dụ :

mô-đun
module Food
  class Bacon; end
  class Chocolate; end
end

puts "Classes defined inside #{Food}:"

puts Food.constants

Ngoài ra, bạn có thể sử dụng một chuỗi như "Array" và lấy lớp thực tế:

array_class = Object.const_get("Array")

Nhưng hãy cẩn thận với điều đó vì người dùng có thể chèn mã nếu chuỗi đến từ params hoặc một số hình thức nhập liệu khác của người dùng.

Trong Rails, có phương thức Constantize về cơ bản thực hiện const_get cho bạn, nhưng hãy nhớ rằng nó không thực hiện bất kỳ kiểm tra bảo mật nào.

CheatSheet

Mọi thứ bạn cần biết về các hằng số Ruby

Phạm vi không đổi của Ruby

Khi bạn tạo một hằng số bên ngoài bất kỳ lớp nào, ở cấp cao nhất của mã của bạn, hằng số đó sẽ có sẵn ở bất cứ đâu.

Các hằng số cũng có sẵn trong các lớp con.

class A
  FOO = 1
end

class B < A
  def foo
    puts FOO
  end
end

B.constants

# [:FOO]

Các hằng số được định nghĩa bên ngoài một mô-đun hoặc lớp lồng nhau cũng có sẵn bên trong các lớp 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"

Trộn mô-đun

Các hằng số từ các mô-đun được kết hợp cũng có sẵn:

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 bao gồm mô-đun, nó sẽ không hoạt động nếu bạn đang mở rộng 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 bao gồm từ một mô-đun, Ruby sẽ tìm kiếm các hằng số bắt đầu từ nơi phương thức đó được định nghĩa.

Ví dụ :

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

Một điều cần ghi nhớ!

Lồng mô-đun

Tôi muốn cho bạn xem thêm một ví dụ với các lớp lồng nhau (tương tự cho các mô-đun).

class A
  FOO = 1
end

class A::B
  class C
    puts FOO
  end
end

Lưu ý A::B ký hiệu ở đây, mà chúng tôi đã cố gắng sử dụng làm phím tắt. Nhưng vấn đề là lớp C sẽ không có quyền truy cập vào FOO trực tiếp.

Vì lý do đó, bạn muốn gắn bó với loại lồng này:

class A
  FOO = 1
end

class A
  class B
    class C
      puts FOO
    end
  end
end

Trong ví dụ đầu tiên, bạn vẫn có thể thực hiện ::A::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.

::A::FOO này cú pháp hoạt động vì nó yêu cầu Ruby tìm trong phạm vi cấp cao nhất, nơi các hằng số như Array &String được xác định.

Video

Tóm tắt

Bạn đã học về hằng số 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ẽ in ra một cảnh báo.

Bạn cũng biết rằng tên lớp là hằng số và bạn nên tránh const_get với đầu vào của người dùng.

Nếu bạn thích bài đăng này đừng quên chia sẻ nó để nhiều người có thể hiểu cách hoạt động của hằng số.