รับรายการวิธีการอินสแตนซ์ของคลาส


98

ฉันมีคลาส:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

ฉันจะได้รับรายการของวิธีการของฉันในระดับนี้ ( method1, method2, method3)?

คำตอบ:


116

คุณต้องการจริงๆTestClass.instance_methodsเว้นแต่คุณจะสนใจในสิ่งที่TestClassตัวเองทำได้

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

TestClass.methods.grep(/method1/) # => []
TestClass.instance_methods.grep(/method1/) # => ["method1"]
TestClass.methods.grep(/new/) # => ["new"]

หรือคุณสามารถเรียกmethods(ไม่instance_methods) บนวัตถุ:

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]

3
เฮ้คุณเอาชนะฉันไป 47 วินาที +1
Phrogz

2
เมื่อฉันลองprint TestClass.new.instance_methodsฉันได้รับข้อผิดพลาดนี้my_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Vladimir Tsukanov

คุณต้องทำTestClass.new.methodsเท่านั้น บางที "มัน" อาจจะคลุมเครือในคำตอบของฉัน
Andrew Grimm

โปรดทราบว่าภายใต้ Ruby 1.9+ อาร์เรย์ของชื่อเมธอดเป็นสัญลักษณ์ไม่ใช่สตริง
Phrogz

1
@Phrogz: ใช่ แต่คุณได้รับอนุญาตให้ใช้นิพจน์ทั่วไปกับพวกเขา คุณไม่ได้อัญเชิญคธูลู! :) แม้ว่าคุณจะได้รับ[:method1]แทน
Andrew Grimm

114
TestClass.methods(false) 

เพื่อรับเฉพาะเมธอดที่เป็นของคลาสนั้นเท่านั้น

TestClass.instance_methods(false) จะส่งคืนวิธีการจากตัวอย่างที่คุณกำหนด (เนื่องจากเป็นวิธีการตัวอย่างของ TestClass)


2
นี่เป็นวิธีที่ดีในการทดสอบว่าคลาสมีเมธอดแบบ polymorphed จากคลาสพื้นฐานหลอก / อินเตอร์เฟสหลอกโดยไม่ต้องพยายามเรียกใช้เมธอดโดยตรง
Daniel Doezema

2
คำตอบที่ได้รับการยอมรับนั้นยอดเยี่ยม แต่นี่เป็นสิ่งที่ผู้คนจะมาที่นี่มากขึ้น
Aaron

นี่ควรเป็นคำตอบที่ได้รับการยอมรับอย่างแน่นอน ขอบคุณ!
Vinicius Brasil

@Aaron: ผมมีข้อสงสัยอย่างมากว่าตั้งแต่คำตอบนี้เป็นที่ไม่ถูกต้อง Object#methodsผลตอบแทนที่ได้วิธีการที่คุณสามารถเรียกบนวัตถุ วิธีใดที่คุณสามารถเรียกใช้กับวัตถุได้? คนที่กำหนดไว้ในของชั้น ซึ่งหมายความว่าTestClass.methodsจะส่งคืนรายการของวิธีการที่คุณสามารถเรียกใช้TestClassซึ่งเป็นวิธีการที่กำหนดไว้ในคลาสของมัน อะไรคือสิ่งที่TestClassระดับ 's? มันคือClass. ดังนั้นTestClass.methodsจะช่วยให้คุณวิธีการที่กำหนดไว้ในไม่คนที่มีการกำหนดไว้ในClass TestClassไม่แน่ใจว่าคำตอบนี้ได้รับการโหวตถึง 116 ครั้งเมื่อมีใครแม้แต่
Jörg W Mittag

…ความรู้ในการส่งผ่านระยะไกลที่สุดจะรับรู้ได้ทันทีว่าผิด หรือคุณก็รู้เพียงแค่คัดลอกและวางรหัสนี้และเรียกใช้รหัสนี้จะแสดงให้เห็นว่าผิด
Jörg W Mittag

39
TestClass.instance_methods

หรือไม่มีวิธีการที่สืบทอดมาทั้งหมด

TestClass.instance_methods - Object.methods

(คือ 'TestClass.methods - Object.methods')


25
หรือไม่มีวิธีการสืบทอด: TestClass.methods(false).
sawa

2
@sawa TestClass.methods(false)กลับว่างเปล่า
Vladimir Tsukanov

1
คำตอบนี้ไม่ถูกต้อง ผลที่จะได้รวมmethod1, method2หรือmethod3เป็นผู้ที่มีวิธีการของอินสแตนซ์ของชั้นไม่ได้วิธีการของTestClassวัตถุเอง
ร็อกซ์

1
@Phrogz: อ๊ะ ... ใช่ 'TestClass.instance_methods - Object.methods' หรือ 'TestClass.new.methods - Object.methods' ... ที่จะสอนฉันไม่ให้เปิดคอนโซล ฉันจะลบคำตอบนี้หรือแก้ไขได้ดีที่สุด
Pavling

1
@Pavling แก้ไขคำตอบของคุณให้ถูกต้องแน่นอน (อย่างรวดเร็วก่อนที่ OP จะกำหนดเครดิตให้คนอื่น! :)
Phrogz



2

อ้างอิงจาก Ruby Doc instance_methods

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

module A
  def method1()  
    puts "method1 say hi"
  end
end
class B
  include A #mixin
  def method2()  
     puts "method2 say hi"
  end
end
class C < B #inheritance
  def method3() 
     puts "method3 say hi"
  end
end

มาดูผลลัพธ์กัน

A.instance_methods(false)
  => [:method1]

A.instance_methods
  => [:method1]
B.instance_methods
 => [:method2, :method1, :nil?, :===, ...# ] # methods inherited from parent class, most important :method1 is also visible because we mix module A in class B

B.instance_methods(false)
  => [:method2]
C.instance_methods
  => [:method3, :method2, :method1, :nil?, :===, ...#] # same as above
C.instance_methods(false)
 => [:method3]

1

หากต้องการรับเฉพาะวิธีการของตัวเองและยกเว้นวิธีที่สืบทอดมา:

จากภายในอินสแตนซ์:

self.methods - self.class.superclass.instance_methods

จากด้านนอก:

TestClass.instance_methods - TestClass.superclass.instance_methods

เพิ่มลงในชั้นเรียน:

class TestClass
  class << self
    def own_methods
      self.instance_methods - self.superclass.instance_methods
    end
  end
end

TestClass.own_methods
=> [:method1, :method2, :method3]

(ทับทิม 2.6.x)

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