2015-05-15 13 views
9

Używam case składni Ruby założyć jakąś prostą logikę opartą na self.class następująco:Dlaczego self.class === MyClass zwraca false, a self.class == MyClass zwraca wartość true?

case self.class 
when FirstClass 
    do stuff.... 
when SecondClass 
    do other stuff... 
end 

Szybko zrozumiałem, to zawsze wraca nil. Po bliższym badaniu, stwierdziliśmy, że case wykorzystuje === zamiast == sprawdzić równość. Po uruchomieniu self.class == FirstClass w moim terminalu otrzymuję true zgodnie z oczekiwaniami, jednak self.class === FirstClass zwraca false.

Patrząc docs rubinowe, znalazłem following explanation z ===:

Case Równości - dla klasy Object, skutecznie takie same jak zawijających # ==, ale zazwyczaj przesłonięta przez potomków, aby zapewnić znaczące semantyki w instrukcjach case.

Czy ktokolwiek może rzucić nieco światła na to, co się dzieje? Z góry dziękuję.

+0

Nie było to dla mnie pouczające, ale klasa opuściła moduł, którego === impl jest tutaj: http://ruby-doc.org/core-2.2.0/Module.html#3D -3D-3D-metoda –

+0

http://stackoverflow.com/questions/4467538/what-does-the-operator-do-in-ruby – Dreamweaver

+0

http://truffles.me.uk/rubys-equality-operator – oobivat

Odpowiedz

5

Kluczem jest „typowo przesłonięte przez potomków, aby zapewnić znaczące semantykę w sprawozdaniach przypadek”, w szczególności Module overrides it:

sprawie Równości - Zwraca true jeśli obj jest instancją mod lub jednego z potomków mod. Ograniczone użycie dla modułów, ale może być używane w instrukcjach case do klasyfikowania obiektów według klas.

Więc dla modułów === działa bardzo podobnie do sposobu is_a? (w rzeczywistości to po prostu wywołuje tę samą funkcję wykonawczą w MRI Ruby rb_obj_is_kind_of). W twoim przykładzie wartość ta wynosi false, ponieważ self.class nie jest instancją FirstClass. Prawdopodobnie jest to instancja o numerze Class. self sam jednak może być instancją:

case self 
when FirstClass 
    do stuff.... 
when SecondClass 
    do other stuff... 
end 

(chociaż myślę, że twój projekt nie może mieć rację, testując klasę obiektu jest zazwyczaj zapach kod Zamiast tego prawdopodobnie powinny mieć różne implementacje metody in. obiekty.)

+0

Miło, działa jak urok (również świetne wyjaśnienie). Re. zapachu kodu: Zdecydowanie zgadzam się, jest to rodzaj funky przypadek użycia - "case" sprawdza klasy, a następnie wywołuje odpowiednią odmianę metody. Normalnie po prostu rzuciłbym metody w swoich klasach, ale w tym przypadku próbuję uzyskać całą logikę związaną z określoną funkcją w jednym miejscu. – Zensaburou

+0

Dobra odpowiedź. Innym przykładem jest [Regexp # ===] (http://ruby-doc.org/core-2.1.4/Regexp.html#method-i-3D-3D-3D). Na przykład '/ a/=== 'cat' # => true', ale tak naprawdę jest używane tylko w instrukcjach' case': 'case 'cat'; kiedy/a/... '. –

Powiązane problemy