Saya dapat dengan mudah naik hierarki kelas di Ruby:
String.ancestors # [String, Enumerable, Comparable, Object, Kernel]
Enumerable.ancestors # [Enumerable]
Comparable.ancestors # [Comparable]
Object.ancestors # [Object, Kernel]
Kernel.ancestors # [Kernel]
Apakah ada cara untuk menurunkan hierarki juga? Saya ingin melakukan ini
Animal.descendants # [Dog, Cat, Human, ...]
Dog.descendants # [Labrador, GreatDane, Airedale, ...]
Enumerable.descendants # [String, Array, ...]
tapi sepertinya tidak ada descendants
metode.
(Pertanyaan ini muncul karena saya ingin menemukan semua model dalam aplikasi Rails yang turun dari kelas dasar dan mencantumkannya; Saya memiliki pengontrol yang dapat bekerja dengan model seperti itu dan saya ingin dapat menambahkan model baru tanpa harus memodifikasi controller.)
singleton_class
alih-alihClass
membuatnya lebih cepat (lihat sumber di apidock.com/rails/Class/descendants )ObjectSpace
tidak akan memilikinya.Object
danBasicObject
?, Penasaran ingin tahu apa yang mereka tunjukkanp ObjectSpace.each_object(Class)
akan mencetak semua kelas. Anda juga bisa mendapatkan turunan dari kelas apa pun yang Anda inginkan dengan mengganti namanyaself
pada baris kode dalam metode ini.Jika Anda menggunakan Rails> = 3, Anda memiliki dua opsi. Gunakan
.descendants
jika Anda ingin lebih dari satu tingkat kedalaman kelas anak-anak, atau gunakan.subclasses
untuk tingkat pertama kelas anak-anak.Contoh:
sumber
Ruby 1.9 (atau 1.8.7) dengan iterators berantai bagus:
Ruby pra-1.8.7:
Gunakan seperti ini:
sumber
ObjectSpace.each_object(::Class)
- ini akan menjaga kode berfungsi ketika Anda memiliki YourModule :: Kelas didefinisikan.Mengganti metode kelas dengan nama inherited . Metode ini akan melewati subkelas ketika dibuat yang dapat Anda lacak.
sumber
Atau (diperbarui untuk ruby 1.9+):
Cara yang kompatibel dengan Ruby 1.8:
Perhatikan bahwa ini tidak akan berfungsi untuk modul. Juga, YourRootClass akan disertakan dalam jawaban. Anda dapat menggunakan Array # - atau cara lain untuk menghapusnya.
sumber
ObjectSpace.each_object(class<<MyClass;self;end) {|it| puts it}
class<<some_obj;self;end
mengembalikan singleton_class objek. Di 1.9+ Anda bisa menggunakansome_obj.singleton_class
(memperbarui jawaban saya untuk mencerminkan itu). Setiap objek adalah turunan dari singleton_class, yang berlaku untuk kelas juga. Karena Each_object (SomeClass) mengembalikan semua instance SomeClass, dan SomeClass adalah turunan dari SomeClass.singleton_class, Each_object (SomeClass.singleton_class) akan mengembalikan SomeClass dan semua subclass.Meskipun menggunakan karya ObjectSpace, metode kelas yang diwariskan tampaknya lebih cocok di sini di bawah (Ruby subclass) dokumentasi
Objectspace pada dasarnya adalah cara untuk mengakses apa saja dan segala sesuatu yang saat ini menggunakan memori yang dialokasikan, jadi iterasi setiap elemen untuk memeriksa apakah itu adalah subkelas dari kelas Animal yang tidak ideal.
Dalam kode di bawah ini, metode kelas Hewan yang diwariskan mengimplementasikan panggilan balik yang akan menambahkan subkelas yang baru dibuat ke array turunannya.
sumber
Saya tahu Anda bertanya bagaimana melakukan ini dalam warisan tetapi Anda dapat mencapai ini dengan langsung di Ruby dengan spasi nama kelas (
Class
atauModule
)Ini jauh lebih cepat dengan cara ini dibandingkan dengan membandingkan setiap kelas
ObjectSpace
seperti yang diusulkan solusi lain.Jika Anda benar-benar membutuhkan ini dalam warisan, Anda dapat melakukan sesuatu seperti ini:
tolok ukur di sini: http://www.eq8.eu/blogs/13-ruby-ancestors-descendants-and-other-annoying-relatives
memperbarui
pada akhirnya yang harus Anda lakukan adalah ini
terima kasih @ saturnflyer atas sarannya
sumber
(Rails <= 3.0) Atau Anda dapat menggunakan ActiveSupport :: DescendantsTracker untuk melakukan akta. Dari sumber:
Karena modularisasinya bagus, Anda bisa 'memilih-ceri' modul tertentu untuk aplikasi Ruby Anda.
sumber
Ruby Facets memiliki keturunan Class #,
Ini juga mendukung parameter jarak generasi.
sumber
Versi sederhana yang memberikan array semua keturunan kelas:
sumber
#subclasses
ini dari Rails ActiveSupport.Anda dapat
require 'active_support/core_ext'
dan menggunakandescendants
metode ini. Periksa dokumen , dan coba IRB atau coba-coba. Dapat digunakan tanpa Rel.sumber
using Rails
dalam arti holistik.Rails menyediakan metode subclass untuk setiap objek, tetapi tidak didokumentasikan dengan baik, dan saya tidak tahu di mana itu didefinisikan. Ini mengembalikan array nama kelas sebagai string.
sumber
Menggunakan permata descendants_tracker dapat membantu. Contoh berikut disalin dari dokumen permata:
Permata ini digunakan oleh permata virtus populer , jadi saya pikir ini cukup solid.
sumber
Metode ini akan mengembalikan hash multidimensi dari semua keturunan Obyek.
sumber
Jika Anda memiliki akses ke kode sebelum subkelas dimuat, Anda dapat menggunakan metode yang diwarisi .
Jika Anda tidak (yang bukan kasus tetapi mungkin berguna bagi siapa saja yang menemukan posting ini) Anda bisa menulis:
Maaf jika saya melewatkan sintaks tetapi ide harus jelas (saya tidak memiliki akses ke ruby saat ini).
sumber