Bạn có thể đặt tên thay thế cho phương thức Ruby theo hai cách:
- alias (keyword)
- alias_method
Nhưng tại sao lại có đến 2 phương thức thực hiện chung 1 mục đích? Hãy cùng khám phá những điểm khác biệt của chúng để hiểu rõ hơn!
The alias Keyword
Đầu tiên chúng ta có alias, đó là một từ khóa Ruby (như if, def, class, v.v.)
Nó trông như thế này:
1 2 3 | alias print_something puts print_something 1 |
Bây giờ call print_something sẽ giống như việc call puts vậy
Alias có một số đặc điểm thú vị sau:
- Nó có cú pháp đặc biệt
- Nó có thể được sử dụng ở bất kỳ đâu
- Có thể alias các biến toàn cục (Nhưng đừng làm vậy nhé)
Những cú pháp hợp lệ:
1 2 3 4 5 6 | alias a b alias :a :b alias :"#{}" :b |
Lưu ý rằng không có dấu phẩy giữa các arguments như trong một phương thức thông thường.
Nếu bạn muốn dynamic method names, bạn có thể làm như thế này…
1 2 3 4 5 | a = :print_something b = :puts alias :"#{a}" :"#{b}" |
Trông khác là xấu, vì vậy bạn cần sử dụng alias_method để làm điều này.
The alias_method Method
Tiếp theo chúng ta có alias_method.
Bạn không thể sử dụng method này trong một instance method. Nó chỉ có thể được defind trong một class hoặc một module
Đây là mô tả từ tài liệu:
alias_method: “Makes new_name a new copy of the method old_name. This can be used to retain access to methods that are overridden.”
Ví dụ:
1 2 3 4 | class Foo alias_method :print_something, :puts end |
Nó sẽ đặt alias cho phương thức puts là print_something trong class Foo
Bạn cũng có thể dùng string để làm tham số thay vì symbol
Ví dụ:
1 2 3 4 | class Foo alias_method "print_something", "puts" end |
alias vs alias_method
Vậy khi nào sự khác biệt diễn ra?
- Khi bạn muốn tạo một alias với dynamically name (Ví dụ như “abc#{rand}”)
- Khi bạn define alias bên trong một method
Chúng ta đã thấy cách sử dụng alias để tạo dynamic method name ở trên, alias_method cung cấp một cú pháp linh hoạt hơn.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 | class Cat def speak "meow" end alias_method "#{name.downcase}_speak", :speak end p Cat.new.cat_speak # "meow" |
Tuy nhiên như đã nói ở trên, alias_method không thể sử dụng bên trong 1 method, bạn sẽ gặp phải lỗi sau:
undefined method ‘alias_method’ for # (NoMethodError)
Đây là một giải pháp:
1 2 3 4 | def enable_aliased_methods self.class.send(:alias_method, :x, :testing) end |
Tuy nhiên sử dụng alias sẽ ngắn gọn hơn nhiều
1 2 3 4 | def enable_aliased_methods alias :x :testing end |
Vậy điểm khác biệt lớn nhất giữa chúng là:
- Một method được define bởi alias sẽ thuộc về class mà alias được sử dụng
- Một method được define bởi alias_method sẽ thuộc về self, hay class hiện tại tại thời điểm code được chạy
Vậy điểu này có ý nghĩa gì?
Nếu bạn sử dụng alias ở lớp cha thì khi bạn call alias ở lớp con sẽ gọi đến method ở lớp cha
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Parent def method puts "parent" end # alias: alias :operation :method # alias_method: alias_method :operation, :method end class Child < Parent def method puts "children" end end # alias: Parent.new.operation => #parent Child.new.operation => #parent # alias_method: Parent.new.operation => #parent Child.new.operation => #children |
Aliasing Makes a Copy Of The Method
Theo mô tả của alias_method & alias, Ruby tạo một bản sao của phương thức chứ không chỉ là copy tên phương thức.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 | def bacon 123 end alias :x :bacon x # 123 bacon # 123 |
Lúc này, chúng ta đã đặt alias x thành bacon, bây giờ hãy xem điều gì sẽ xảy ra nếu override bacon:
1 2 3 4 5 6 7 8 9 10 | def bacon 234 end x # 123 bacon # 234 |
bacon trả về một giá trị mới còn x thì không.