ฉันควรใช้นามแฝงหรือ alias_method หรือไม่


353

ผมพบว่าการโพสต์ในบล็อกเมื่อเทียบกับalias alias_methodดังที่แสดงในตัวอย่างที่ให้ไว้ในบล็อกโพสต์นั้นฉันเพียงต้องการนามแฝงวิธีการอื่นในชั้นเรียนเดียวกัน ฉันควรใช้แบบไหน ฉันมักจะเห็นการaliasใช้งาน แต่มีคนบอกฉันว่าalias_methodจะดีกว่า

การใช้นามแฝง

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias name full_name
end

User.new.name #=>Johnnie Walker

การใช้ alias_method

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias_method :name, :full_name
end

User.new.name #=>Johnnie Walker

ลิงก์โพสต์บล็อกที่นี่


4
โพสต์นั้นไม่ตอบคำถามของคุณหรือ?
moinudin

4
@marcog: ฉันอ่านมันมาแล้วและฉันก็ไม่เชื่อ การกำหนดนามแฝงภายในวิธีการนั่นไม่ใช่สิ่งที่เราควรทำบ่อยๆ
Boris Stitnicky

2
@digitalextremist ลิงก์ใช้งานได้
lukas.pukenis

4
คู่มือสไตล์ ruby ​​ตอนนี้แนะนำalias"เมื่อ aliasing เมธอดในขอบเขตคลาส lexical" และalias_method"เมื่อ aliasing เมธอดของโมดูลคลาสหรือคลาสเดี่ยวที่รันไทม์" github.com/bbatsov/ruby-style-guide#alias-method-lexically
jtzero

คำตอบ:


380

alias_methodสามารถนิยามใหม่ได้ถ้าต้องการ (มันถูกกำหนดในModuleชั้นเรียน)

aliasพฤติกรรมของการเปลี่ยนแปลงขึ้นอยู่กับขอบเขตและอาจไม่แน่นอนในบางครั้ง

คำตัดสิน: ใช้alias_method- ช่วยให้คุณมีความยืดหยุ่นมากขึ้น

การใช้งาน:

def foo
  "foo"
end

alias_method :baz, :foo

43
คุณหมายถึงอะไรโดยคาดเดาไม่ได้ อย่างใดอย่างหนึ่งจะบอกว่าตัวเลือกที่ยืดหยุ่นน้อยจะคาดเดาได้มากขึ้น นอกจากนี้คุณสามารถให้ตัวอย่างเชิงปฏิบัติของการรับประโยชน์จากการกำหนด alias_method ใหม่ได้หรือไม่
Boris Stitnicky

7
กรณีการใช้งานตัวอย่าง: alias :new_method_name :old_method_nameหรือalias_method :new_method_name, :old_method_name
boulder_ruby

10
คำที่เขามองหาที่นี่เป็นผลลัพธ์ที่คาดหวังมากกว่า alias_methodจะถูกกำหนดที่รันไทม์และไม่เมื่อรหัสที่อ่านเช่นaliasดังนั้นมันจะทำงานมากขึ้นวิธีการที่เราจะคาดหวังว่ามันจะ
Joshua Pinter

4
คาดหวังว่าวิธีการที่กำหนดไว้ในระหว่างการบินไม่ได้เป็นสิ่งที่โปรแกรมเมอร์ส่วนใหญ่คาดหวัง อย่างน้อยมันก็เหมือนหมูที่บินมาหาฉัน
akostadinov

10
หนึ่งอาจโต้เถียงกันสำหรับdefvs. define_method: " define_methodสามารถกำหนดใหม่ได้ถ้าจำเป็นต้อง (มันถูกกำหนดในModuleชั้นเรียน) defพฤติกรรมของการเปลี่ยนแปลงขึ้นอยู่กับขอบเขตและสามารถคาดเดาไม่ได้ค่อนข้างครั้งคำตัดสิน: ใช้define_method- มันช่วยให้คุณตัน ความยืดหยุ่นมากขึ้น "
Daniel Rikowski

62

นอกเหนือจากไวยากรณ์ความแตกต่างที่สำคัญคือในการกำหนดขอบเขต :

# 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'

ในวิธีการกรณีข้างต้น“ ชื่อ” เลือกวิธี“ full_name” ที่กำหนดในคลาส“ นักพัฒนา” 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'

ด้วยการใช้นามแฝงวิธีการ "ชื่อ" ไม่สามารถเลือกวิธี“ full_name” ที่กำหนดในนักพัฒนา

นี่เป็นเพราะaliasเป็นคำหลักและมีการกำหนดขอบเขตศัพท์ มันหมายความว่ามันจะถือว่าselfเป็นมูลค่าของตัวเองในเวลาที่อ่านซอร์สโค้ด ในทางตรงกันข้ามalias_methodถือว่าselfเป็นค่าที่กำหนดในเวลาทำงาน

ที่มา: http://blog.bigbinary.com 2012/ 01/08/alias-vs-alias-method.html


35

จุดในความโปรดปรานของaliasแทนที่จะalias_methodเป็นความหมายว่าเป็นที่ยอมรับโดย RDOC นำไปอ้างอิงข้ามเรียบร้อยในเอกสารที่สร้างขึ้นในขณะที่ RDOC alias_methodสมบูรณ์ไม่สนใจ


56
บางที RDoc ควรเริ่มรักษา alias_method เหมือนกับ alias เราควรบอกพวกเขาเกี่ยวกับเรื่องนี้;)
Szymon Jeż

9
RDoc ควรเข้าใจถึงผลที่ตามมาของวิธีการประเมินที่รันไทม์อย่างไร

@ user1115652 คุณมีจุดที่ใครบางคนอาจมีการแก้ไขลิงalias_methodหรือไม่? ดูเหมือนจะไม่น่าเป็นไปได้จริงและถ้าใครทำอย่างนั้นพวกเขาก็ควรจะเต็มใจที่จะได้รับผลกระทบใน RDoc หากประเด็นของคุณคือสิ่งที่เป็นไปไม่ได้คุณคิดว่าทำไมและคุณคิดว่า Yardoc ทำเช่นนั้น?
iconoclast

35

ฉันคิดว่ามีกฎที่ไม่ได้เขียนไว้ (เช่นการประชุม) ที่บอกว่าใช้ 'นามแฝง' เพื่อลงทะเบียนชื่อนามแฝงเมธอดซึ่งหมายความว่าถ้าคุณต้องการให้ผู้ใช้รหัสของคุณหนึ่งวิธีที่มีชื่อมากกว่าหนึ่งชื่อ:

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

หากคุณต้องการที่จะขยายรหัสของคุณใช้ทางเลือกทับทิมทับทิม

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

หนึ่งปีหลังจากถามคำถามจะมีบทความใหม่เกี่ยวกับเรื่องนี้:

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

ดูเหมือนว่า "ผู้ชายหลายคนจิตใจมากมาย" จากผู้เขียนบทความอดีตกระตุ้นให้เกิดการใช้งานในขณะที่หลังแนะนำให้ใช้alias_methodalias

อย่างไรก็ตามมีภาพรวมทั่วไปของวิธีการเหล่านี้ทั้งในบล็อกและคำตอบด้านบน:

  • ใช้aliasเมื่อคุณต้องการ จำกัด นามแฝงให้อยู่ในขอบเขตที่กำหนดไว้
  • ใช้alias_methodเพื่ออนุญาตให้คลาสที่สืบทอดมาเพื่อเข้าถึง

16

ผู้ให้อัญมณี rubocop เสนอในRuby Style Guideของพวกเขา:

ชอบนามแฝงเมื่อใช้นามแฝงวิธีการในขอบเขตระดับคำศัพท์เป็นความละเอียดของตัวเองในบริบทนี้ก็เป็นคำศัพท์และมันสื่อสารอย่างชัดเจนกับผู้ใช้ว่าการเปลี่ยนทิศทางของนามแฝงของคุณจะไม่ถูกเปลี่ยนที่รันไทม์หรือโดยคลาสย่อยใด ๆ

class Westerner
  def first_name
   @names.first
  end

 alias given_name first_name
end

ใช้ alias_method ทุกครั้งเมื่อใช้นามแฝงวิธีการของโมดูลคลาสหรือคลาสซิงเกิลที่รันไทม์เนื่องจากขอบเขตของนามแฝงนำไปสู่ความไม่แน่นอนในกรณีเหล่านี้

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จะถูกประกาศในชั้นเรียนหรือโมดูลซึ่งกำลังได้รับการสืบทอดในชั้นเรียนของเราตอนนี้ที่จะใช้new_method

สิ่งเหล่านี้สามารถเป็นตัวแปรหรือวิธีการทั้งสอง

สมมติว่า Class_1 มี old_method และ Class_2 และ Class_3 ทั้งคู่จะได้รับ Class_1

หากการกำหนดค่าเริ่มต้นของ Class_2 และ Class_3 เสร็จสิ้นใน Class_1 จากนั้นทั้งสองสามารถมีชื่อแตกต่างกันใน Class_2 และ Class_3 และการใช้งาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.