แทนที่จะสนับสนุนเมธอด overloading Ruby จะเขียนทับเมธอดที่มีอยู่ ทุกคนสามารถอธิบายได้หรือไม่ว่าทำไมภาษานี้ได้รับการออกแบบในลักษณะนี้?
แทนที่จะสนับสนุนเมธอด overloading Ruby จะเขียนทับเมธอดที่มีอยู่ ทุกคนสามารถอธิบายได้หรือไม่ว่าทำไมภาษานี้ได้รับการออกแบบในลักษณะนี้?
คำตอบ:
วิธีการบรรทุกเกินพิกัดสามารถทำได้โดยการประกาศสองวิธีที่มีชื่อเดียวกันและลายเซ็นที่แตกต่างกัน ลายเซ็นที่แตกต่างเหล่านี้สามารถเป็นได้ทั้ง
method(int a, int b) vs method(String a, String b)method(a) vs method(a, b)เราไม่สามารถใช้วิธีการมากเกินไปได้โดยใช้วิธีแรกเนื่องจากไม่มีการประกาศชนิดข้อมูลเป็นทับทิม ( ภาษาที่พิมพ์แบบไดนามิก ) ดังนั้นวิธีเดียวที่จะกำหนดวิธีการข้างต้นคือdef(a,b)
ด้วยตัวเลือกที่สองอาจดูเหมือนว่าเราสามารถใช้วิธีการมากไป แต่เราทำไม่ได้ สมมุติว่าฉันมีสองวิธีที่มีจำนวนอาร์กิวเมนต์ต่างกัน
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one, 
# so here is the problem.ดังนั้นทับทิมจำเป็นต้องรักษาวิธีหนึ่งในวิธีการค้นหาห่วงโซ่ที่มีชื่อที่ไม่ซ้ำกัน
"การบรรทุกเกินพิกัด" เป็นคำศัพท์ที่ไม่มีความหมายในรูบี มันเป็นพื้นไวพจน์ "ส่งข้อโต้แย้งตามคงที่" แต่ทับทิมไม่ได้มีการจัดส่งแบบคงที่ทั้งหมด ดังนั้นเหตุผลที่ทับทิมไม่สนับสนุนการแจกแจงแบบคงที่ตามข้อโต้แย้งเพราะมันไม่สนับสนุนการแจกแจงคงที่ระยะเวลา มันไม่รองรับการส่งแบบคงที่ทุกชนิดไม่ว่าจะตามอาร์กิวเมนต์หรืออย่างอื่น
ตอนนี้ถ้าคุณไม่ได้ถามเฉพาะเกี่ยวกับการบรรทุกเกินพิกัด แต่อาจเกี่ยวกับการจัดส่งตามอาร์กิวเมนต์แบบไดนามิกคำตอบคือ: เนื่องจาก Matz ไม่ได้ใช้งาน เพราะไม่มีใครสนใจที่จะเสนอ เพราะไม่มีใครสนใจที่จะใช้มัน
โดยทั่วไปการจัดส่งอาร์กิวเมนต์ตามแบบไดนามิกในภาษาที่มีการขัดแย้งที่ไม่จำเป็นและรายการอาร์กิวเมนต์ตัวแปรที่มีความยาวเป็นอย่างมากยากที่จะได้รับสิทธิและแม้ยากที่จะให้มันเข้าใจ แม้ในภาษาที่มีการแจกแจงแบบอิงอาร์กิวเมนต์แบบคงที่และไม่มีอาร์กิวเมนต์ที่เป็นตัวเลือก (เช่น Java เป็นต้น) บางครั้งแทบเป็นไปไม่ได้เลยที่จะบอกว่าเป็นเพียงมนุษย์ธรรมดาซึ่งจะมีการเลือกเกินพิกัด
ใน C # คุณสามารถเข้ารหัสปัญหา 3-SAT ใด ๆลงในการแก้ปัญหาการโอเวอร์โหลดซึ่งหมายความว่าการแก้ไขการโอเวอร์โหลดใน C # นั้นเป็น NP-hard
ตอนนี้ให้ลองด้วยการจัดส่งแบบไดนามิกที่คุณมีมิติเวลาเพิ่มเติมเพื่อให้อยู่ในหัวของคุณ
มีภาษาที่จัดส่งแบบไดนามิกตามข้อโต้แย้งทั้งหมดของขั้นตอนเมื่อเทียบกับภาษาเชิงวัตถุซึ่งส่งเฉพาะในselfข้อโต้แย้งซีร็อ ธ "ซ่อน" ยกตัวอย่างเช่น Common Lisp ในประเภทแบบไดนามิกและแม้กระทั่งค่าแบบไดนามิกของการขัดแย้งทั้งหมด Clojure ยื้อกับฟังก์ชั่นโดยพลการของข้อโต้แย้งทั้งหมด (ซึ่ง BTW จะเย็นมากและมีประสิทธิภาพมาก)
แต่ฉันไม่รู้ภาษา OO ใด ๆ กับการแจกจ่ายตามอาร์กิวเมนต์แบบไดนามิก มาร์ตินโอเดอร์ สกี บอกว่าเขาอาจพิจารณาเพิ่มการจัดส่งอาร์กิวเมนต์ที่ใช้ในการ Scala แต่เพียงว่าเขาสามารถลบมากไปในเวลาเดียวกันและจะย้อนกลับเข้ากันได้ทั้งที่มีอยู่รหัสสกาล่าที่ใช้มากไปและเข้ากันได้กับ Java (เขากล่าวถึงโดยเฉพาะอย่างยิ่ง Swing และ AWT ซึ่งเล่นเทคนิคที่ซับซ้อนมากบางอย่างออกกำลังกายสวยมากทุกกรณีมุมมืดของกฎการโอเวอร์โหลดค่อนข้างซับซ้อนของ Java) ฉันมีความคิดบางอย่างเกี่ยวกับการเพิ่มการส่งแบบอิงอาร์กิวเมนต์ไปที่ Ruby แต่ฉันไม่สามารถหาวิธีที่จะทำในลักษณะที่เข้ากันได้ย้อนหลัง
def method(a, b = true)ไม่ทำงาน" ดังนั้นการโอเวอร์โหลดวิธีจึงเป็นไปไม่ได้ " มันไม่ใช่; มันเป็นเรื่องยาก ฉันพบคำตอบนี้ให้ข้อมูลจริงๆ
                    ฉันคิดว่าคุณกำลังมองหาความสามารถในการทำเช่นนี้:
def my_method(arg1)
..
end
def my_method(arg1, arg2)
..
endRuby สนับสนุนสิ่งนี้ในวิธีที่แตกต่าง:
def my_method(*args)
  if args.length == 1
    #method 1
  else
    #method 2
  end
endรูปแบบทั่วไปก็จะผ่านในตัวเลือกเป็นแฮ:
def my_method(options)
    if options[:arg1] and options[:arg2]
      #method 2
    elsif options[:arg1]
      #method 1
    end
end
my_method arg1: 'hello', arg2: 'world'หวังว่าจะช่วย
วิธีการบรรทุกเกินพิกัดทำให้รู้สึกในภาษาที่มีการพิมพ์แบบคงที่ซึ่งคุณสามารถแยกความแตกต่างระหว่างประเภทของการขัดแย้ง
f(1)
f('foo')
f(true)เช่นเดียวกับระหว่างจำนวนอาร์กิวเมนต์ที่ต่างกัน
f(1)
f(1, 'foo')
f(1, 'foo', true)ความแตกต่างแรกไม่มีอยู่ในทับทิม Ruby ใช้การพิมพ์แบบไดนามิกหรือ "การพิมพ์เป็ด" ความแตกต่างที่สองสามารถจัดการได้โดยอาร์กิวเมนต์เริ่มต้นหรือโดยทำงานกับอาร์กิวเมนต์:
def f(n, s = 'foo', flux_compensator = true)
   ...
end
def f(*args)
  case args.size
  when  
     ...
  when 2
    ...
  when 3
    ...
  end
endนี่ไม่ได้ตอบคำถามที่ว่าทำไม ruby ไม่มีเมธอดมากเกินไป แต่ห้องสมุดบุคคลที่สามสามารถให้บริการได้
contracts.rubyห้องสมุดช่วยให้การบรรทุกเกินพิกัด ตัวอย่างที่ดัดแปลงจากบทช่วยสอน:
class Factorial
  include Contracts
  Contract 1 => 1
  def fact(x)
    x
  end
  Contract Num => Num
  def fact(x)
    x * fact(x - 1)
  end
end
# try it out
Factorial.new.fact(5)  # => 120โปรดทราบว่าสิ่งนี้มีประสิทธิภาพมากกว่าการบรรทุกเกินพิกัดของ Java เพราะคุณสามารถระบุค่าที่จะจับคู่ (เช่น1) ไม่ใช่เพียงพิมพ์
คุณจะเห็นประสิทธิภาพลดลงโดยใช้สิ่งนี้แม้ว่า; คุณจะต้องใช้การวัดประสิทธิภาพเพื่อตัดสินใจว่าคุณสามารถทนได้เท่าไหร่
ฉันมักจะทำโครงสร้างต่อไปนี้:
def method(param)
    case param
    when String
         method_for_String(param)
    when Type1
         method_for_Type1(param)
    ...
    else
         #default implementation
    end
endสิ่งนี้อนุญาตให้ผู้ใช้ของวัตถุใช้เมธอด clean_name: method ที่ชัดเจน แต่ถ้าเขาต้องการเพิ่มประสิทธิภาพการประมวลผลเขาสามารถเรียกเมธอดที่ถูกต้องได้โดยตรง
นอกจากนี้ยังทำให้การทดสอบและนักพนันดีขึ้น
มีคำตอบที่ดีอยู่แล้วว่าทำไมด้านข้างของคำถาม อย่างไรก็ตามหากใครที่กำลังมองหาวิธีแก้ไขปัญหาอื่น ๆ ก็สามารถเช็คเอาต์อัญมณีทับทิมซึ่งเป็นแรงบันดาลใจจากคุณสมบัติการจับคู่รูปแบบของ Elixir
 class Foo
   include Functional::PatternMatching
   ## Constructor Over loading
   defn(:initialize) { @name = 'baz' }
   defn(:initialize, _) {|name| @name = name.to_s }
   ## Method Overloading
   defn(:greet, :male) {
     puts "Hello, sir!"
   }
   defn(:greet, :female) {
     puts "Hello, ma'am!"
   }
 end
 foo = Foo.new or Foo.new('Bar')
 foo.greet(:male)   => "Hello, sir!"
 foo.greet(:female) => "Hello, ma'am!"