Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Làm chủ phạm vi biến và Object Binding trong Ruby

Phạm vi (scope) là khái niệm quan trọng mà mọi lập trình viên Ruby cần hiểu.

Tại sao?

Bởi vì nó là nguồn gốc của nhiều thông báo lỗi và sự nhầm lẫn.

Phạm vi là gì?

Phạm vi đề cập đến những biến nào có sẵn tại một thời điểm nhất định.

Các loại biến khác nhau có phạm vi khác nhau.

Một phạm vi có thể rất hẹp (biến cục bộ) hoặc rất rộng (biến toàn cục).

Bạn nên dùng phạm vi hẹp nhất có thể để tránh vấn đề về biến đổi trạng thái và va chạm tên.

Dưới đây là danh sách ví dụ về cách phạm vi ảnh hưởng đến code Ruby của bạn.

Phạm vi biến cục bộ (Local Variable Scope)

Biến cục bộ có phạm vi hẹp nhất.

Cụ thể, biến cục bộ được định nghĩa bên trong phương thức sẽ không còn tồn tại sau khi phương thức trả về.

Ví dụ:

a = 50
def apple
  a = 100
  puts a
end

Bạn nghĩ apple sẽ in ra gì?

Đáp án:

Khi bạn gọi apple, nó sẽ luôn in 100.

Việc a được định nghĩa bên ngoài phương thức là 50 không có tác động nào đến biến a bên trong phương thức.

Chúng là các biến khác nhau.

Bạn có thể tưởng tượng phạm vi như một bong bóng xà phòng…

a = 50 đầu tiên nằm trong một bong bóng, sau đó khi bạn gọi một phương thức, BẤT KỲ phương thức nào, bạn bước vào một bong bóng MỚI RỖNG.

Bạn không mang theo bất kỳ biến cục bộ nào qua bong bóng mới.

Và khi phương thức kết thúc…

Bong bóng vỡ.

Các biến bên trong bong bóng biến mất và bạn không thể truy cập chúng.

Đó là cách biến cục bộ hoạt động.

Phạm vi biến instance (Instance Variable Scope)

Biến instance có phạm vi rộng hơn.

Cụ thể, chúng được dùng để chia sẻ dữ liệu bên trong một đối tượng Ruby.

Ví dụ:

class Fruit
  def more_juice
    @quantity = 100
  end
  def less_juice
    @quantity = 50
  end
end

Trong ví dụ này, @quantity là cùng một biến cho cả phương thức more_juice và less_juice.

Đó là giá trị chia sẻ giữa các phương thức.

Nhưng bên ngoài class này, và thậm chí trên các đối tượng Fruit khác nhau, @quantity sẽ khác nhau.

Ví dụ:

orange = Fruit.new
apple = Fruit.new
orange.more_juice
apple.less_juice

Mỗi đối tượng có tập hợp biến instance riêng.

Vì vậy trong ví dụ này, orange sẽ có @quantity là 100, và apple sẽ có @quantity là 50.

Giống như mỗi người có tên, tuổi, quốc gia khác nhau.

Cách phạm vi hoạt động trong Block

Block rất thú vị khi nói đến phạm vi.

Nếu tiếp tục so sánh với bong bóng, block làm là mang theo biến cục bộ từ bong bóng hiện tại.

Bạn có thể truy cập và thay đổi chúng.

Ví dụ:

a = []
3.times { a << 1 }
p a # [1, 1, 1]

NHƯNG…

Bong bóng vẫn vỡ, loại bỏ bất kỳ biến cục bộ MỚI nào được tạo bên trong block.

Thú vị phải không?

Ví dụ về điều tôi nói:

1.times { b = [1,2,3] }
b # NameError

Không chỉ thế, block còn mang theo bong bóng tại thời điểm nó được tạo.

Hiệu ứng này gọi là "closure" (đóng gói).

Hãy nhớ, "bong bóng" này là tập hợp tất cả biến có thể truy cập tại một điểm cụ thể trong code nguồn.

Đó chính là phạm vi bản thân, được đóng gói thành một đối tượng.

Trong Ruby chúng ta gọi đây là Binding.

Cách sử dụng Ruby Bindings

Một khái niệm nữa tôi muốn chia sẻ trong bài này là về bindings.

Bạn có thể lưu tất cả các bong bóng chúng ta đã nói vào một đối tượng Ruby, một đối tượng của lớp Binding.

Ví dụ:

def banana
  a = 100
  binding
end
banana.class # Binding

Đối tượng binding này chính là bong bóng.

Bạn thậm chí có thể nhìn vào bên trong bong bóng và xem có gì.

Ví dụ:

banana.send(:local_variables) # [:a]

Còn về Rails Scopes thì sao?

Scope trong Rails là một khái niệm khác hoàn toàn so với scope trong Ruby.

Vậy, scope trong Rails là gì?

Đó là cách đặt tên cho một truy vấn cơ sở dữ liệu tùy chỉnh, được cấu thành từ các phương thức ActiveRecord.

Ví dụ:

class User < ApplicationRecord
  scope(:with_email) { where.not(email: nil) }
end
User.with_email

Đừng nhầm lẫn điều này với khái niệm scope trong Ruby 🙂

Tóm tắt

Bạn đã học về scopes và binding objects trong Ruby!

Hãy nhớ rằng phạm vi định nghĩa những biến bạn có thể truy cập tại bất kỳ thời điểm nào.

Nó giống như một bong bóng, biến cục bộ có bong bóng riêng, trong khi các đối tượng chia sẻ một bong bóng khác cho biến instance.

Cảm ơn bạn đã đọc.