2012-01-02 19 views
7

Son zamanlarda bazı Ruby meta-programlama üzerinde çalışıyordum ve assigning anonymous classes to constants hakkında merak ediyordum. Bu sınıfınAnonim sınıflar bir sabite atandığında bir kanca var mı?

anonymous_class = Class.new # => #<Class:0x007f9c5afb21d0> 

Yeni örneklerini oluşturulabilir::

an_instance = anonymous_class.new # => #<#<Class:0x007f9c5afb21d0>:0x007f9c5afb0330> 

Şimdi, ne zaman anonim sınıf atanan Ruby

, aşağıdaki gibi anonim bir sınıf oluşturmak mümkündür Bir sabit, sınıf şimdi uygun bir ada sahip:

Foo = anonymous_class # => Foo 

an_instance # => #<Foo:0x007f9c5afb0330> 

Sorum: isimsiz sınıf sabit atanan an için bir kanca yöntemi var mı bu sınıfın bir örneği de şimdi?

Yakut'ta çok sayıda hooks methods var, ancak bunu bulamadım.

+0

Çok ilginç bir soru. –

+1

AFAIK, değişken atamalar için sabit veya başka bir şekilde hala kanca yok ([aynı soru için uzun süre önce buraya bakın] (http://www.ruby-forum.com/topic/65720)). Globals, evet. –

cevap

6

Sürekli atamanın dahili olarak nasıl çalıştığına bir göz atalım. Takip eden kod, ruby-1.9.3-p0'un bir kaynak tarball'undan çıkarılır. Öncelikle (sabitlerini atamak için kullanılır) VM talimatı setconstant tanımına bakalım:

# /insns.def, line 239 
DEFINE_INSN 
setconstant 
(ID id) 
(VALUE val, VALUE cbase) 
() 
{ 
    vm_check_if_namespace(cbase); 
    rb_const_set(cbase, id, val); 
    INC_VM_STATE_VERSION(); 
} 

burada vm_check_if_namespace veya INC_VM_STATE_VERSION bir kanca yerleştirmek için hiçbir fırsatı. Bu yüzden rb_const_set bakmak (variable.c: 1886), her bir sabit atanır denir işlevi: Hatta sabit atandı ilk kez çağrılmadı tüm kodu kaldırıldı

# /variable.c, line 1886 
void 
rb_const_set(VALUE klass, ID id, VALUE val) 
{ 
    rb_const_entry_t *ce; 
    VALUE visibility = CONST_PUBLIC; 

    # ... 

    check_before_mod_set(klass, id, val, "constant"); 
    if (!RCLASS_CONST_TBL(klass)) { 
     RCLASS_CONST_TBL(klass) = st_init_numtable(); 
    } 
    else { 
     # [snip], won't be called on first assignment 
    } 

    rb_vm_change_state(); 

    ce = ALLOC(rb_const_entry_t); 
    ce->flag = (rb_const_flag_t)visibility; 
    ce->value = val; 

    st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); 
} 

bir modülün içinde. Daha sonra buna göre çağrılan tüm fonksiyonlara baktım ve Ruby kodundan bir kanca yerleştirebileceğimiz tek bir nokta bulamadım. Bu, bir şeyi kaçırmadığı sürece, bir sabit atamayı (en azından MRI'da) no no'lu yoldan çıkarmanın zor gerçek olduğu anlamına gelir.

Güncelleme

netleştirmek için: Anonim sınıf (Andrew yanıtında doğru belirtildiği gibi) atanır atanmaz sihirli kısa sürede yeni bir isim alamadım yapar. Aksine, sınıfın nesne kimliği ile birlikte sabit isim, Ruby'nin dahili sabit arama tablosunda saklanır. Bundan sonra, sınıfın adı istenirse, artık uygun bir adla (ve sadece Class:0xXXXXXXXX...) çözülebilir.

Bu ödeve yanıt vermek için yapabileceğiniz en iyi şey, nil olmayan (bu büyük bir kaynak israfı olan IMHO olana kadar) arka plan çalışanı iş parçacığının döngüsünde sınıfın name numarasını denetlemektir.

+0

Çok kapsamlı yanıt için teşekkürler. Tamamlamak için bu referansı "setconstant" olarak nasıl buldunuz? Kaynaktaki ('insns.def') belgeleme benim için çok açık değil:" sabit değişken kimliği belirle. Eğer klass Qfalse ise, sabit bu kapsamda erişebilir. Eğer klass Qnil ise, üst seviye sabitini ayarla. aksi halde, klass sınıfı veya modülü altında sabiti ayarlayın. " Bu kod gerçekten (anonim) sınıf örneklerine sabit atamak için mi kullanılıyor? – rdvdijk

+0

@rdvdijk: "printf" ile tahmin ettim ve doğruladım. –

+0

Burada referans verdiğiniz kaynak kodunu inceledim ve yapıştırdığınız kodun anlamını anladım. Ancak, sorumu tamamen cevaplamıyor. Bu kod, sabitlerin atanmasının ele alınmasını ve bu kodun kullanılabilir bir kanca olmadığını gösterir. Ancak, bu, anonim sınıfın yeni adı hakkında ne zaman ve nerede bulunduğunu açıklamamaktadır. Andrew Grimm'ın cevabını takiben “classname” ve ilgili kodun “RCLASS_CONST_TBL” ya da “rb_class_tbl” değişkenlerine baktığı anlaşılıyor, değil mi? – rdvdijk

0

Anonim sınıflar, bir sabite atandıklarında aslında adlarını almazlar. Bir daha ne zaman adlarının ne olduğunu sorduklarında anlıyorlar.

Bunun için bir başvuru bulmaya çalışacağım. Düzenleme: Bir tane bulamıyorum, üzgünüm.

+0

Anahtar, 'variable.c: 305' (ruby-1.9.3-p0)' de tanımlanan 'rb_class_name' işlevini ve onun tarafından çağrılan işlevlerdir (özellikle' find_class_path', 'RCLASS_CONST_TBL' kullanan haritalar olup olmadığını kontrol etmek için kullanılır. sınıf, en azından benim yorumum doğruysa, bir isme bağlıdır. –

İlgili konular