Tôi nên sử dụng bí danh hoặc bí danh?


353

Tôi tìm thấy một bài viết trên blog aliasso với alias_method. Như được hiển thị trong ví dụ được đưa ra trong bài đăng trên blog đó, tôi chỉ đơn giản muốn bí danh một phương thức khác trong cùng một lớp. Tôi nên sử dụng cái nào? Tôi luôn thấy aliassử dụng, nhưng ai đó nói với tôi alias_methodlà tốt hơn.

Sử dụng bí danh

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias name full_name
end

User.new.name #=>Johnnie Walker

Cách sử dụng alias_method

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias_method :name, :full_name
end

User.new.name #=>Johnnie Walker

Blog bài viết liên kết ở đây


4
Không phải bài viết đó trả lời câu hỏi của bạn?
moinudin

4
@marcog: Tôi đã đọc qua và tôi không bị thuyết phục. Xác định bí danh bên trong các phương thức, đó không phải là điều người ta nên làm thường xuyên.
Boris Stitnicky

2
Liên kết @digitalextremist hoạt động
lukas.pukenis

4
Hướng dẫn kiểu ruby ​​hiện khuyên dùng alias"khi các phương thức răng cưa trong phạm vi lớp từ vựng" và alias_method"khi các phương thức bí danh của các mô-đun, lớp hoặc các lớp đơn lẻ trong thời gian chạy" github.com/bbatsov/ruby-style-guide#alias-method-lexical
jtzero

Câu trả lời:


380

alias_methodcó thể được xác định lại nếu cần. (nó được định nghĩa trong Modulelớp.)

aliasHành vi của chúng thay đổi tùy thuộc vào phạm vi của nó và đôi khi có thể khá khó đoán.

Nhận định: Sử dụng alias_method- nó mang lại cho bạn sự linh hoạt hơn.

Sử dụng:

def foo
  "foo"
end

alias_method :baz, :foo

43
Bạn có ý nghĩa gì bởi không thể đoán trước. Ngây thơ, người ta sẽ nói rằng tùy chọn kém linh hoạt hơn sẽ dễ dự đoán hơn. Ngoài ra, bạn có thể cung cấp bất kỳ ví dụ thực tế nào về việc hưởng lợi từ việc xác định lại alias_method không?
Boris Stitnicky

7
trường hợp sử dụng ví dụ: alias :new_method_name :old_method_nameHOẶCalias_method :new_method_name, :old_method_name
boulder_ruby

10
Từ anh ấy tìm kiếm ở đây là kết quả mong đợi hơn . alias_methodđược xác định trong thời gian chạy chứ không phải khi mã được đọc, như aliasvậy, vì vậy nó hoạt động nhiều hơn như chúng ta mong đợi .
Joshua Pinter

4
mong đợi rằng các phương thức được xác định một cách nhanh chóng trong thời gian chạy không phải là điều mà hầu hết các lập trình viên mong đợi. Ít nhất nó giống như lợn bay với tôi.
akostadinov

10
Người ta có thể lập luận tương tự cho defso với define_method: " define_methodcó thể được xác định lại nếu cần. (Nó được xác định trong Modulelớp.) defThay đổi hành vi tùy thuộc vào phạm vi của nó và đôi khi có thể khá khó đoán. Phán quyết: Sử dụng define_method- nó mang lại cho bạn một tấn linh hoạt hơn. "
Daniel Rikowski

62

Ngoài cú pháp, sự khác biệt chính là trong phạm vi :

# scoping with alias_method
class User

  def full_name
    puts "Johnnie Walker"
  end

  def self.add_rename
    alias_method :name, :full_name
  end

end

class Developer < User
  def full_name
    puts "Geeky geek"
  end
  add_rename
end

Developer.new.name #=> 'Geeky geek'

Trong trường hợp trên, phương thức tên của tên Cameron chọn phương thức Full fullameame được định nghĩa trong lớp Developer Developer. Bây giờ hãy thử với alias.

class User

  def full_name
    puts "Johnnie Walker"
  end

  def self.add_rename
    alias name full_name
  end
end

class Developer < User
  def full_name
    puts "Geeky geek"
  end
  add_rename
end

Developer.new.name #=> 'Johnnie Walker'

Với việc sử dụng bí danh, phương thức tên Tên không thể chọn phương thức Full fullameame được xác định trong Nhà phát triển.

Điều này là bởi vì aliaslà một từ khóa và nó có phạm vi từ vựng. Nó có nghĩa là nó coi selfgiá trị của bản thân tại thời điểm mã nguồn được đọc. Ngược lại alias_methodcoi selfgiá trị được xác định tại thời điểm chạy.

Nguồn: http://blog.bigbinary.com/2012/01/08/alias-vs-alias-method.html


35

Một điểm có lợi aliasthay vì alias_methodlà ngữ nghĩa của nó được công nhận bởi ndoc, dẫn đến các tham chiếu chéo gọn gàng trong tài liệu được tạo, trong khi đó, hoàn toàn bỏ qua alias_method.


56
Có lẽ RDoc nên bắt đầu đối xử với alias_method giống như bí danh. Chúng ta nên nói với họ về điều đó;)
Szymon Jeż

9
Làm thế nào để RDoc hiểu được hậu quả của một phương thức được đánh giá trong thời gian chạy?

@ user1115652 Quan điểm của bạn rằng ai đó có thể đã vá khỉ alias_method? Điều đó dường như thực sự không thể xảy ra, và nếu ai đó làm điều đó, thì họ nên sẵn sàng gánh chịu hậu quả trong RDoc. Nếu quan điểm của bạn là không thể, thì tại sao bạn lại nghĩ như vậy và bạn nghĩ Yardoc làm điều đó như thế nào?
iconoclast

35

Tôi nghĩ rằng có một quy tắc bất thành văn (giống như quy ước) nói rằng sử dụng 'bí danh' chỉ để đăng ký bí danh tên phương thức, nghĩa là nếu bạn muốn cung cấp cho người dùng mã của bạn một phương thức có nhiều hơn một tên:

class Engine
  def start
    #code goes here
  end
  alias run start
end

Nếu bạn cần mở rộng mã của mình, hãy sử dụng thay thế meta ruby.

class Engine
  def start
    puts "start me"
  end
end

Engine.new.start() # => start me

Engine.class_eval do
  unless method_defined?(:run)
    alias_method :run, :start
    define_method(:start) do
      puts "'before' extension"
      run()
      puts "'after' extension"
    end
  end
end

Engine.new.start
# => 'before' extension
# => start me
# => 'after' extension

Engine.new.run # => start me

23

Một năm sau khi đặt câu hỏi, một bài viết mới về chủ đề này:

http://erniemiller.org/2014/10/23/in-defense-of-alias/

Dường như "rất nhiều đàn ông, rất nhiều tâm trí". Từ bài viết trước tác giả khuyến khích sử dụng alias_method, trong khi bài viết sau gợi ý sử dụngalias .

Tuy nhiên, có một tổng quan chung về các phương pháp này trong cả hai blog và câu trả lời ở trên:

  • sử dụng alias khi bạn muốn giới hạn răng cưa trong phạm vi được xác định
  • sử dụng alias_methodđể cho phép các lớp kế thừa truy cập nó

16

Những người đóng góp đá quý rubocop đề xuất trong Hướng dẫn phong cách Ruby của họ :

Thích các bí danh khi các phương thức bí danh trong phạm vi lớp từ vựng vì độ phân giải của bản thân trong ngữ cảnh này cũng là từ vựng, và nó thông báo rõ ràng cho người dùng rằng việc xác định bí danh của bạn sẽ không bị thay đổi khi chạy hoặc bởi bất kỳ lớp con nào trừ khi được nêu rõ.

class Westerner
  def first_name
   @names.first
  end

 alias given_name first_name
end

Luôn sử dụng alias_method khi các phương thức bí danh của các mô-đun, lớp hoặc lớp đơn trong thời gian chạy, vì phạm vi từ vựng của bí danh dẫn đến không thể đoán trước trong các trường hợp này

module Mononymous
  def self.included(other)
    other.class_eval { alias_method :full_name, :given_name }
  end
end

class Sting < Westerner
  include Mononymous
end

0

alias_method new_method , old_method

old_method sẽ được khai báo trong một lớp hoặc mô-đun hiện đang được kế thừa cho lớp của chúng tôi nơi new_method sẽ được sử dụng.

đây có thể là biến hoặc phương pháp cả.

Giả sử Class_1 có old_method và Class_2 và Class_3 cả hai đều kế thừa Class_1.

Nếu, việc khởi tạo Class_2 và Class_3 được thực hiện trong Class_1 thì cả hai có thể có tên khác nhau trong Class_2 và Class_3 và cách sử dụng của nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.