Dapatkan daftar metode instance kelas

98

Saya ada kelas:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

Bagaimana saya bisa mendapatkan daftar metode saya di kelas ini ( method1, method2, method3)?

Vladimir Tsukanov
sumber

Jawaban:

115

Anda benar-benar menginginkannya TestClass.instance_methods, kecuali jika Anda tertarik pada apa yang TestClassdapat dilakukannya.

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"]

Atau Anda dapat memanggil methods(tidak instance_methods) pada objek:

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]
Andrew Grimm
sumber
3
Heh, Anda mengalahkan saya dengan 47 detik. +1
Phrogz
2
Ketika saya mencoba print TestClass.new.instance_methods, saya mendapatkan kesalahan inimy_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Vladimir Tsukanov
Anda hanya perlu melakukan TestClass.new.methods. Mungkin "itu" ambigu dalam jawaban saya.
Andrew Grimm
Perhatikan bahwa di bawah Ruby 1.9+, larik nama metode adalah simbol, bukan string.
Phrogz
1
@Phrogz: Ya, tetapi Anda diizinkan untuk menggunakan ekspresi reguler pada mereka. Anda bahkan tidak memanggil Cthulhu! :) Meskipun Anda akan mendapatkan [:method1]sebagai gantinya.
Andrew Grimm
113
TestClass.methods(false) 

untuk mendapatkan hanya metode yang dimiliki kelas itu saja.

TestClass.instance_methods(false) akan mengembalikan metode dari contoh yang Anda berikan (karena mereka adalah metode instance TestClass).

Bijan
sumber
2
Ini adalah cara yang bagus untuk menguji apakah suatu kelas memiliki metode polimorf dari kelas dasar Antarmuka-semu / Abstrak tanpa harus mencoba dan memanggil metode secara langsung.
Daniel Doezema
2
Jawaban yang diterima memang bagus, tetapi yang ini kemungkinan akan membuat lebih banyak orang akan datang ke sini!
Aaron
Ini pasti harus menjadi jawaban yang diterima. TERIMA KASIH!
Vinicius Brasil
38
TestClass.instance_methods

atau tanpa semua metode yang diwariskan

TestClass.instance_methods - Object.methods

(Sebelumnya 'TestClass.methods - Object.methods')

Pavling
sumber
25
atau tanpa metode diwariskan: TestClass.methods(false).
sawa
2
@sawa TestClass.methods(false)kembali kosong
Vladimir Tsukanov
1
Jawaban ini salah; hasilnya tidak akan termasuk method1,, method2atau method3, karena itu adalah metode dari instance kelas, bukan metode dari TestClassobjek itu sendiri.
Phrogz
1
@Phrogz: Ups ... ya, 'TestClass.instance_methods - Object.methods', atau 'TestClass.new.methods - Object.methods' ... itu akan mengajari saya untuk tidak menjalankan konsol. Apakah yang terbaik bagi saya untuk menghapus jawaban ini, atau mengeditnya?
Pavling
1
@Pavling Sunting jawaban Anda agar benar. (Cepat, sebelum OP memberikan kredit kepada orang lain! :)
Phrogz
6

Anda bisa mendapatkan daftar yang lebih rinci (misalnya terstruktur dengan mendefinisikan kelas) dengan permata seperti debugging atau looksee .

J -_- L
sumber
6
$ irb --simple-prompt

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

tc_list = TestClass.instance_methods(false)
#[:method1, :method2, :method3]
puts tc_list
#method1
#method2
#method3
Douglas G. Allen
sumber
2
Ini terlalu mirip dengan jawaban lain dan tidak menambahkan informasi atau kejelasan tambahan.
Substansial
3
Anda gagal mengatakan bahwa ini juga sangat terlambat. : D
Douglas G. Allen
2

Menurut instance_methods Ruby Doc

Mengembalikan larik yang berisi nama metode instance publik dan dilindungi di penerima. Untuk modul, ini adalah metode publik dan dilindungi; untuk kelas, mereka adalah metode instance (bukan tunggal). Jika parameter opsional salah, metode dari setiap leluhur tidak disertakan. Saya mengambil contoh dokumentasi resmi.

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

Mari kita lihat hasilnya.

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]
Mukesh Kumar Gupta
sumber
0

Untuk hanya mendapatkan metode sendiri, dan mengecualikan yang diwariskan:

Dari dalam contoh:

self.methods - self.class.superclass.instance_methods

Dari luar:

TestClass.instance_methods - TestClass.superclass.instance_methods

Tambahkan ke kelas:

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

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

(dengan ruby ​​2.6.x)

nakwa
sumber