BẮT ĐẦU
KIỂU DỮ LIỆU
TOÁN TỬ
NÂNG CAO
INTERVIEW
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
Dự án mới của mình là gamehow.net, mời anh em ghé thăm và góp ý ạ.

Hiểu về Method Missing trong Ruby

Trong bài này chúng ta sẽ tìm hiểu Method Missing trong Ruby, đây là một khái niệm muốn nói đến một phương thức không tồn tại trong Ruby, nên hiểu nó sẽ giúp ích cho bạn rất nhiều trong quá trình làm việc với Ruby.

1. Method missing là gì ?

Chắc hẳn với các lập trình viên chúng ta ai cũng có thể đôi lần dù cố tình hay vô tình gọi đến một method không tồn tại. Điều này thì chắc chắn sẽ gây ra thông báo lỗi mặc định của Ruby rồi.

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Thế nhưng Ruby đã xử lý như thế nào với những method không tồn tại này thì trong bài này mình sẽ giới thiệu cho các bạn một phương thức mà Ruby đã gọi tới là chính là method missing.

Đúng như tên gọi của nó method_missing, thì chúng ta cũng có thể hiểu được nôm na chức năng của phương thức này là gì. Nó sẽ được gọi tới khi mà một method được gọi không tồn tại.

2. Method lookup

Để có một cái nhìn rõ hơn về method missing thì trước tiên chúng ta nên tìm hiểu xem khi nào thì method này được gọi tới.

class Animal
  def hello
    puts "Hello animal"
  end
end

class Dog < Animal

end

a = Dog.new

puts a.hello # Hello animal

Theo như ví dụ ở trên thì chúng ta có một đối tượng được tạo ra từ class Dog được kế thừa từ class Animal. Chúng ta gọi đến một phương thức có tên là hello, thế nhưng rõ ràng trong class Dog** không hề tồn tại do đó nó đã tiếp tục gọi đến superclass của nó đó là Animal.

Và cứ như thế nếu như Animal không tồn tại phương thức hello thì nó sẽ lần lượt gọi tới các superclass khác để tìm kiếm phương thức này. Nếu như không tìm thấy thì method cuối cùng được gọi tới chính là method_missing. Đây là một private method được xây dựng sẵn của class BasicObject.

Mà theo như Ancestors chain của một class thì

Class.ancestors

=> [Class, Comparable, Object, Kernel, BasicObject]

Nếu như bạn không biết Ancestors chain là gì thì mình sẽ giải thích đơn giản như sau

  • Tất cả các class mà nó kế thừa.
  • Tất cả các module được mix trong nó.

Do class được kế thừa từ tổ tiên của nó là BasicObject nên nó sẽ sử dụng được method_missing.

Nếu như bạn hỏi tại sao mà mình biết nó thuộc class BasicObject thì mở terminal lên và gõ ngay lệnh

BasicObject.private_methods.sort

để xác thực nhé :D

Trong cây phân lớp class thì BasicObject là tổ tiên cuối cùng của mọi class khác.

3. No method error

Chúng ta có một ví dụ đơn giản

class Dog
    def talk
       puts "Dog go go"
   end
end

dog = Dog.new

puts dog.talk

Kết quả

Dog go go

Kết quả vẫn hoạt động bình thường thế nhưng hãy thử gọi lại một phương thức không tồn tại.

puts dog.eat

# Kết quả

Traceback (most recent call last):

method_missing.rb:8:in `<main>': undefined method `eat' for #<Dog:0x000055632c3cc550> (NoMethodError)

Vậy là con dog của chúng ta không có chức năng ăn rồi, chúng ta sẽ nhận được ngay được thông báo lỗi của chương trình NoMethodError, và cũng thấy Ruby log luôn lỗi tại file nào và dòng nào luôn theo như log được hiển thị.

Thế nhưng bây giờ thay vì muốn nhận được một Exception error thì chúng ta muốn nhận được một message rõ ràng hơn thay vì nhận được một message mặc định của Ruby. Thì đây là lúc chúng ta sử dụng tới method_missing rồi đây.

4. Cú pháp và cách sử dụng

Để khai báo một method missing trong Ruby thì ta sử dụng cú pháp sau.

def method_missing method_name, *args, &block
  # code
end

Cú pháp cũng giống như các phương thức khác và trong method này sẽ nhận vào các tham số như

  • method_name: Tên của phương thức được gọi tới mà không tồn tại/ không được định nghĩa
  • *arg: Đây là một mảng các tham số chứa các giá trị của các tham số được truyền vào phương thức không tồn tại
  • &block: Tham số này không bắt buộc, nó thể hiện phương thức đang được gọi có đi kèm một block ở tận cùng.

Lưu ý: Kiểu dữ liệu mà method_name trả về sẽ là một Symbol nhé

Thử viết lại một message khác mà chúng ta muốn thay vì là sử dụng Exception Error của Ruby mặc định. Để làm được việc này chúng ta chỉ cần overwrite lại phương thức method_missing của class BasicObject.

class Dog
    def talk
       puts "Dog go go"
   end

   def method_missing method_name, *arg
      if method_name.to_s == 'eat'
        puts "Dog don't need eat"
      else
        super
      end
    end
end

dog = Dog.new

puts dog.eat

Kết quả khi chạy chương trình

Dog don't need eat

Kết quả đã ra đúng như mong muốn. Giờ tiếp tục thử với một method không tồn tại khác xem sao

puts dog.run

# kết quả

method_missing.rb:10:in `method_missing': undefined method `run' for #<Dog:0x0000563740d04210> (NoMethodError)

Kết quả lại trả về NoMethodError như ban đầu. Đơn giản vì trên đoạn code trên chúng ta chỉ kiểm tra đối với nếu method được gọi tới có tên là eat còn nếu không sẽ nhảy vào else và gọi tới super. Từ khóa này sẽ gọi lại phương thức method_missing của BasicObject.

2. Kết luận

Qua bài bài này chúng ta đã cùng đi tìm hiểu xong cách sử dụng một method missing trong Ruby, từ đó cũng hiểu luôn khi nào thì phương thức này được gọi tới.

Khi mà các bạn làm việc với Ruby on Rails (một framework của Ruby) thì đã có một vài các phương thức mà họ sử dụng method_missing để định nghĩa các hàm có sẵn có thể gọi, nếu không nó cũng sẽ gọi tới keyword super để gọi phương thức method_missing trong BasicObject giống như cách mà chúng ta đã làm ở trên.

Cùng chuyên mục:

Block trong Ruby

Block trong Ruby

Block là một khối lệnh được đặt trong ...

Iterator trong Ruby

Iterator trong Ruby

Ở bài trước mình có nói với các bạn về việc sử dụng các vòng…

Vòng lặp trong Ruby: Vòng lặp for / while / until / loop

Vòng lặp trong Ruby: Vòng lặp for / while / until / loop

Khi học một ngôn ngữ lập trình thì không thể không tìm hiểu tới một…

Câu lệnh điều kiện trong Ruby

Câu lệnh điều kiện trong Ruby

Trong bài này chúng ta sẽ học các lệnh điều kiện trong Ruby, đây là…

Các toán tử trong Ruby

Các toán tử trong Ruby

Nói đến toán tử thì dù bạn học ngôn ngữ nào đi nữa thì việc…

Cách sử dụng Ranges trong Ruby

Cách sử dụng Ranges trong Ruby

Ví dụ bạn cần tạo ra một dãy từ 1 đến 100 thì có thể…

Cách sử dụng Array trong Ruby

Cách sử dụng Array trong Ruby

Đây cũng là một trong những kiểu dữ liệu phổ biến nhất, vì vậy bạn…

Kiểu dữ liệu Symbol trong Ruby

Kiểu dữ liệu Symbol trong Ruby

Symbol giống như một String thế nhưng Symbol là một chuỗi bất biến nghĩa là…

Kiểu dữ liệu Text trong Ruby (còn gọi là chuỗi / string)

Kiểu dữ liệu Text trong Ruby (còn gọi là chuỗi / string)

Kiểu dữ liệu Boolean trong Ruby: True, False và Nil

Kiểu dữ liệu Boolean trong Ruby: True, False và Nil

Boolean là kiểu dữ liệu rất quan trọng, nó được dùng rất nhiều trong những…

Kiểu dữ liệu Hashes trong Ruby: Hiểu từ đơn giản đến phức tạp

Kiểu dữ liệu Hashes trong Ruby: Hiểu từ đơn giản đến phức tạp

Nếu bạn đã từng làm việc với một vài ngôn ngữ khác trước khi mà…

Kiểu dữ liệu Number trong Ruby (Kiểu số Integer, Float, ...)

Kiểu dữ liệu Number trong Ruby (Kiểu số Integer, Float, ...)

Trước tiên, chúng ta cùng nhìn qua một bức ảnh tổng quát phân cấp các…

Ruby là gì? Ai đã sáng tạo ra ngôn ngữ viêm kim cương này?

Ruby là gì? Ai đã sáng tạo ra ngôn ngữ viêm kim cương này?

Từ những năm 2008, thời mà mình còn học đại học thì Ruby là ngôn…

Các loại biến và cách sử dụng Module trong Ruby

Các loại biến và cách sử dụng Module trong Ruby

Bất kì một ngôn ngữ lập trình nào đều có khái niệm biến và ruby…

Cách tạo Method - Class và Object trong Ruby

Cách tạo Method - Class và Object trong Ruby

Trong bài này mình sẽ hướng dẫn các bạn cách tạo hàm, gọi hàm. Cách…

Cú pháp trong Ruby - Chạy Hello World

Cú pháp trong Ruby - Chạy Hello World

Tổng quan về cú pháp trong ruby. Hướng dẫn tạo file và chạy hello world…

Hướng dẫn cài đặt Ruby trên Window, Linux và MacOS

Hướng dẫn cài đặt Ruby trên Window, Linux và MacOS

Hướng dẫn chi tiết cách thiết lập môi trường lập trình Ruby trên hệ điều…

Top