Trong class của Ruby, đôi lúc chúng ta muốn lấy ra giá trị của biến instance (các biến được định nghĩa với ký hiệu @) để các class khác sử dụng mà vẫn đảm bảo tính encapsulation của OOP. Trong trường hợp đó, chúng ta sử dụng các phương thức getter và setter. Các phương thức này cho phép chúng ta truy cập vào một biến instance của class từ những class bên ngoài. Trong đó các phương thức getter được sử dụng để lấy giá trị của biến và các phương thức setter được sử dụng để đặt giá trị của biến ở những class nhất định hoặc phiên thực hiện.
# Getter method
class Text def initialize text @text = text end def get_text @text end
end # Create an object
text = Text.new "getter method"
puts text.get_text Output:
getter method
Trong ví dụ, chúng ta chỉ có thể lấy giá trị của biến @text thông qua get_text method và mặc định không thể trực tiếp lấy giá trị của biến @text từ bên ngoài class.
# Setter method
class Text def initialize text @text = text end def get_text @text end def set_text new_text @text = new_text end
end # Create an object
text = Text.new "getter method"
puts text.get_text # Change value of the object from outside
text.set_text = "setter method"
puts text.get_text Outputs:
getter method
setter method
Ở ví dụ này, nếu chúng ta không xác định phương thức set_text trong class, thì không thể thay đổi giá trị của biến instance trong class. Với sự trợ giúp của phương thức setter này, chúng ta đã sử dụng lại cùng một đối tượng cho nhiều đoạn texts khác nhau.
Bên cạnh đó, có thể nhận thấy rằng khi class phát triển dần, số lượng phương thức getter và setter tăng lên nhiều và hầu hết đều tuân theo cùng một định dạng như trên. Để giảm thiểu số dòng code, Ruby cung cấp cho chúng ta một cách nhanh chóng để tạo Các phương thức này được gọi là phương thức accessor. Mục đích của chúng cũng giống như phương thức getter hoặc setter.
Có 3 loại accessors trong Ruby:
- attr_reader: Getter method
- attr_writer: Setter method
- attr_accessor: Getter and Setter methods
class Text def initialize text @get_text = text @set_text = text @get_set_text = text end attr_reader :get_text attr_writer :set_text attr_accessor :get_set_text
end # Create an object
accessor = Text.new "getter method" # Getter method
puts accessor.get_text Output:
getter method # Setter method
accessor.set_text = "setter method"
puts accessor.set_text Output:
NoMethodError # ở đây ta chỉ cho phép thay đổi biến và không khai thác dữ liệu # Getter and Setter methods
puts accessor.get_set_text
accessor.get_set_text = "getter and setter methods"
puts accessor.get_set_text Outputs:
getter method
getter and setter methods
Vậy getter và setter có thể được sử dụng như thế nào, sau đây mình sẽ lấy ví dụ về việc sử dụng như một nơi lưu trữ tạm cho mỗi phiên làm việc.
class Test
# is_image_test dùng để xác định loại bài test có chứa hình ảnh
attr_accessor :is_image_test
validate :custom_value, if: :is_image_test
end
Sử dụng rails c để rõ hơn về cách hoạt động:
puts test.is_image_test
test = Test.new(is_image_test: true)
puts test.is_image_test Output # => nil value
true
Giá trị khởi tạo của is_image_test là nil nên output khi puts sẽ là " " và ta có thể truyền vào giá trị true như trên để xác định có nên validate custom value của record mới hay không (đôi lúc có thể thay cho việc sử dụng một cột ở DB, ...). Và sau khi kết thúc một phiên làm việc bằng Ctrl + D với rails c thì giá trị được đưa về như ban đầu, tương tự như cách làm việc của controller khi kết thúc một request.
Để hiểu rõ hơn về những lợi ích của getter và setter mọi người có thể tham khảo thêm ở bài viết duới đây https://sal.vn/yRbVre. Happy coding!