Hash Parameter - Sử dụng hash làm parameter cho method trong Ruby
Trong Ruby, khi phải khai báo và sử dụng một method có số lượng parameter lớn, lập trình viên thường gặp khó khăn trong việc nhớ đủ các parameter cũng như thứ tự của chúng trong method. Hôm nay mình xin giới thiệu một giải pháp cho vấn đề này. Hash là một tập hợp các cặp giá trị (key - value), ...
Trong Ruby, khi phải khai báo và sử dụng một method có số lượng parameter lớn, lập trình viên thường gặp khó khăn trong việc nhớ đủ các parameter cũng như thứ tự của chúng trong method. Hôm nay mình xin giới thiệu một giải pháp cho vấn đề này.
Hash là một tập hợp các cặp giá trị (key - value), giá trị của value được truy vấn thông qua key. Các thao tác cơ bản trên hash bao gồm khai báo, truy vấn, gán giá trị và tạo mới một cặp giá trị (key - value).
elements = {"H" => "Hydrogen", "Li" => "Lithium"} => {"H" => "Hydrogen", "Li" => "Lithium"} elements["H"] => "Hydrogen" elements["H"] = "Hyrdo" => "Hydro" elements["Ne"] = "Neon" => "Neon"
Giả sử chúng ta khai báo class People như sau.
class People attr_accessor :name, :age, :gender, :job def initialize name, age, gender, job self.name = name self.age = age self.gender = gender self.job = job end def show puts "Name: #{name}" puts "Age: #{age}" puts "Gender: #{gender}" puts "Job: #{job}" end end
Chúng ta khởi tạo một đối tượng, truyền các parameter theo đúng thứ tự và gọi method show trên đối tượng đó.
people = People.new "Tom and Jerry", 10, "Male", "Actor" people.show
Kết quả trả về.
Name: Tom and Jerry Age: 10 Gender: Male Job: Actor
Mọi chuyện vẫn ổn cho đến khi chúng ta quên thứ tự truyền vào của các parameter và gọi method show trên đối tượng đó.
people = People.new "Tom and Jerry", 10, "Actor", "Male" people.show
Kết quả trả vế không còn đúng như ta mong muốn.
Name: Tom and Jerry Age: 10 Gender: Actor Job: Male
Vậy chúng ta phải làm thế nào để phòng tránh trường hợp trên xảy ra?
Sử dụng hash như là parameter của method, ta viết lại class People như sau.
class People attr_accessor :name, :age, :gender, :job def initialize params self.name = params[:name] self.age = params[:age] self.gender = params[:gender] self.job = params[:job] end def show puts "Name: #{name}" h puts "Age: #{age}" puts "Gender: #{gender}" puts "Job: #{job}" end end
Khởi tạo đối tượng, sử dụng hash làm parameter truyền vào và gọi method show trên đối tượng đó.
people = People.new {:name => "Tom and Jerry", :age => 10, :gender => "Male", :job => "Actor"} people.show
Kết quả nhận được.
Name: Tom and Jerry Age: 10 Gender: Actor Job: Male
Chúng ta có thế bó cặp dấu "{}" nếu hash là parameter duy nhất hoặc cuối cùng của method.
people = People.new :name => "Tom and Jerry", :age => 10, :gender => "Male", :job => "Actor" people.show
Nếu chúng ta sử dụng :symbol làm key cho hash, chúng ta có thể bỏ dấu ":" của symbol và thay thế dấu "=>" bằng ":"
people = People.new name: "Tom and Jerry", age: 10, gender: "Male", job: "Actor" people.show
Chuyện gì xảy ra khi lỗi typo xảy ra, chúng ta vô tính gõ sai key của hash (job thành jod).
people = People.new name: "Tom and Jerry", age: 10, gender: "Male", jod: "Actor" people.show
Code vẫn chạy và không raise error, attribute job của people nhận giá trị nil (default value của hash). Vậy chúng ta phải làm thế nào để phòng tránh trường hợp trên xảy ra?
Để phòng tránh lỗi typo bị bỏ qua khi sử dụng hash làm parameter cho method, ta có thể sử khai báo hash với các căp key - value được gán giá trị mặc định. Ta viết lại class People như sau:
class People attr_accessor :name, :age, :gender, :job def initialize name: nil, age: nil, gender: nil, job: nil self.name = name self.age = age self.gender = gender self.job = job end def show puts "Name: #{name}" puts "Age: #{age}" puts "Gender: #{gender}" puts "Job: #{job}" end end
Khởi tạo đối tượng, sử dụng hash làm parameter truyền vào và gọi method show trên đối tượng đó.
people = People.new name: "Tom and Jerry", age: 10, gender: "Male", jod: "Actor" people.show
Khi gặp lỗi typo như đoạn chương trình trên, ruby lập tức raise error và dừng chương trình
unknown keyword: jod (ArgumentError)