2011-01-30 16 views
5

Ruby'de bunu yapmanın en uygun yolu nedir?Ruby deyimi: yöntem çağrısı veya başka bir varsayılan

def callOrElse(obj, method, default) 
    if obj.respond_to?(method) 
    obj.__send__(method) 
    else 
    default 
    end 
end 
+0

EAFP (yani, burada deneyin hariç) Ruby topluluğunda Pythonistas tarafından olduğu gibi kullanılmıyor mu? –

+0

@Karl. Tüm Rubyist'lerden bahsetmiyorum, ama bir kerede yapabileceğiniz bir şey için en az dört satır yazmak zorunda kalmak, birçok Ruby programcısı için kesinlikle can sıkıcıdır (muhtemelen Python'da aklına gelmeyecekleri bir şey). – tokland

+0

Ayrıca, OP niyetinin bir __default__ davranışını içeriyorsa burada bir try/except yapısı kullanmazdım. Benim düşünceme göre, eğer iki yol da (yani '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' – slhck

cevap

3

: Ick zaten güzel bir çözümdür bu davayı im orada olduğunu bildiğim @slhck olduğu gibi

result = obj.method rescue default 

, muhtemelen bu kullanmak ister obj'in yönteme yanıt vermeyeceği makul bir şanstır, ancak bu bir seçenektir.

+2

Basit olduğu gibi, bu, obj.method'un yükseldiği herhangi bir istisnayı gölgelemenin en büyük dezavantajına sahiptir, hiçbir yöntemin olmadığını veya başarısız olduğunu bilemezsiniz. Mümkünse kişisel olarak saklı kalmaktan kaçınacağım. – tokland

+0

-1 @tokland'ın bahsettiği sebepten dolayı. Bunu genel bir strateji olarak kullanamazsınız. – Jazzepi

2

Ben muhtemelen x = obj.method || default benzer bir şey istiyorum Yani

obj.respond_to?(method) ? obj.__send__(method) : default 
+0

Bu daha temiz, ancak aslında aynı işlevsellik. Bunu yapmanın daha iyi bir yolu olacağını düşündüm. – dsg

+0

Peki, aynı _functionality_ değilse ne istiyorsunuz? :) İlgilendiğim kadarıyla, bu kararı atlamanın bir yolu yok. Ama belki birinin bir fikri vardır. – slhck

+0

Şunun gibi bir şey umuyordum: 'x = obj.method || default'. – dsg

3

için gider?

class Object 
    def try_method(name, *args, &block) 
    self.respond_to?(name) ? self.send(name, *args, &block) : nil  
    end 
end 

p "Hello".try_method(:downcase) || "default" # "hello" 
p "hello".try_method(:not_existing) || "default" # "default" 

Belki sembollerle bu dolaylı çağrı sevmiyorum: Yakut ideal Kendi aşağıdan yukarıya yapılar inşa etmek dildir? Hiçbir cepten uzman değilim, ama sen olmadığını bilmeli benim anladığıma:

p "hello".maybe_has_method.not_existing || "default" # "default" 

Yan not: hiçbir sorun, daha sonra Ick 'ın maybe tarzı bakmak ve bir proxy nesnesini kullanın (eğer uygulama anlamaya) Aradığınız nesne gerçekten böyle bir yönteme sahip. Veya nil metodu göndermek için kontrol etmek istediğiniz nesneyi mi? o cevap olarak sunulan edilmemiştir Çünkü object_or_nil.maybe.method || default

+0

Bu genellikle iyi bir yanıttır, ancak uygulamanın "false" veya "nil" değerini döndüren "varsayılan" olan bir yöntemle sonuçlanacağını unutmayın. – Phrogz

+0

@Phrogz: Bu iyi bir nokta, ancak bu durumda varsayılan bir değere ihtiyacınız yoktur, sadece "eğer obj.maybe.enabled?" Durumunu yazınız. Her neyse, her zaman belki desenini ihtiyaçlarınız için ayarlayabilirsin: "obj.maybe (: default => true) .active?", Ancak "|| default" tipik vakaları kapsamalıdır. – tokland

İlgili konular