2009-09-13 15 views
8

Ruby,numaralı nesnesini tanımlar. Nesne. Sürprizim için, bazı sınıflar çağrı yaparken istisnaları artırır. Ben bu davranışı sahip NilClass, TrueClass, FalseClass, Fixnum bulundu.Hangi Ruby sınıfları desteklenir.

1) #clone'a izin vermeyen tam bir sınıf listesi (en azından çekirdek sınıflar) var mı? Veya belirli bir sınıfın #clone destekleyip desteklemediğini algılamanın bir yolu var mı?

2) 42.clone ile ilgili sorun nedir?

+2

Gerçekten sınıf kendimi kopyalanabilen olup olmadığını sınamak nasıl bilmek istiyorum. Bir sınıf kendini klonlamaya izin vermek istemiyorsa, o zaman nesneyi yalnızca public_methods altında test edebilmeniz için Object'ten aldığı klon yöntemini özel yapmalıdır. Benim için sağduyulu gibi görünüyor. –

cevap

7

En azından kaynağın okunmasını saymazsanız resmi bir liste olduğunu düşünmüyorum. 2) çalışmıyor nedeni Fixnums için uygulanan bir optimizasyon nedeniyle. Onlar gerçek değerleriyle (yani doğru, yanlış ve sıfır) içsel olarak saklanır/iletilir ve işaretçi olarak değil. Naif çözüm sadece 42.clone aynı 42 döndürür, ancak sonra değişmez obj.clone.object_id != obj.object_id artık beklemez, 42.clone aslında klonlama olmaz.

+0

'obj.clone.object_id! = Obj.object_id' true ve' obj. clone.object_id == obj.object_id 'her zaman doğru olmamak farklıdır. Birincisi tutmadığı, ikincisinin yaptığı anlamına gelmez. – sawa

0

Değişmez sınıfları klonlayamazsınız. Yani Yalnızca bir nesne 42 nesnesine sahip olabilirsiniz (bir Fixnum olarak), ancak çok sayıda "42" örneğine sahip olabilirsiniz (çünkü dizge değişebilir). Sembolleri klonlayamazsınız çünkü bunlar immutable dizgiler gibi bir şeydir.

Bunu IRB'de object_id yöntemiyle kontrol edebilirsiniz. (semboller ve fixnumlar, tekrar eden çağrılardan sonra size aynı object_id değerini verir)

+1

Mutability bununla hiçbir ilgisi yoktur (aslında, bir Fixnum'a durum ekleyebilirsiniz). – Chuck

+0

Fixnum için gerçekten çok tuhaf varsayılan davranış, özellikle klon yöntemine sahip olduğu düşünüldüğünde, d.class.method_defined? (: Clone) == true –

5

Fixnum, dil tarafından özel bir tedavi verilen özel bir sınıftır. Programınız başladığı andan itibaren, sınıfın temsil edebileceği her sayı için tam olarak bir tane Fixnum vardır ve herhangi bir ekstra alan almayan özel bir temsil verilir - bu şekilde, temel matematik işlemleri tahsis edilmez ve ayrılmaz deli gibi hafıza. Bundan dolayı, birden fazla 42.

Diğerleri için, hepsinin ortak bir özelliği yoktur: onlar singleton'lardır. Tanıma göre tek bir sınıfın yalnızca bir örneği vardır, bu nedenle kopyalamaya çalışmak bir hatadır.

+1

"Bundan dolayı, birden fazla 42 olamaz.". Ve neden olması gerekiyor? Mükemmel. –

1

ben hala düzgün clonability test etmek için nasıl bilmiyorum ama burada hata yakalama kullanarak clonablity test etmek için çok aksak, kötü bir yoldur:

def clonable?(value) 
    begin 
    clone = value.clone 
    true 
    rescue 
    false 
    end 
end 

Ve burada bile klonlamak unclonable konusunda bilgiler. En azından çok az sınıf için yoruldum.

b = :b 
puts "clonable? #{clonable? b}" 

b = proc { b == "b" } 
puts "clonable? #{clonable? b}" 

b = [:a, :b, :c] 
c = super_mega_clone(b) 

puts "c: #{c.object_id}" 
puts "b: #{b.object_id}" 
puts "b == c => #{b == c}" 
b.each_with_index do |value, index| 
    puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}" 
end 
b[0] = :z 

puts "b == c => #{b == c}" 
b.each_with_index do |value, index| 
    puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}" 
end 

b = :a 
c = super_mega_clone(b) 
puts "b: #{b.object_id} c: #{c.object_id}" 

> clonable? false 
> clonable? true 
> c: 2153757040 
> b: 2153757480 
> b == c => true 
> [0] b: 255528 c: 255528 
> [1] b: 255688 c: 255688 
> [2] b: 374568 c: 374568 
> b == c => false 
> [0] b: 1023528 c: 255528 
> [1] b: 255688 c: 255688 
> [2] b: 374568 c: 374568 
> b: 255528 c: 255528 
1

Bir YARV kaynak kodunun git grep "can't clone" ve

lib/singleton.rb: raise TypeError, "can't clone instance of singleton #{self.class}" 
object.c:  rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj)); 
test/test_singleton.rb: expected = "can't clone instance of singleton TestSingleton::SingletonTest" 

birinci ve üçüncü çizgileri

var sen a tek klonlanamaz işaret vermedi: Burada
def super_mega_clone(value) 
    eval(value.inspect) 
end 

bazı örnek testi var .

İkinci satır rb_special_const_p(obj) anlamına gelir. Ama bu benim Ken'in ötesine geçiyor.

İlgili konular