Używam Ruby 1.9.2 i Ruby on Rails 3.2.2. Mam następującą metodę:
# Note: The "class_name" parameter is a constant; that is, it is a model class name.
def my_method(class_name)
case class_name
when Article then make_a_thing
when Comment then make_another_thing
when ... then ...
else raise("Wrong #{class_name}!")
end
end
Chciałbym zrozumieć, dlaczego w case
powyżej, zawsze uruchamia else
„część”, gdy wykonuję wywołania metod, takie jak my_method(Article)
, my_method(Comment)
i tak dalej.
Jak mogę rozwiązać ten problem? Czy ktoś ma radę, jak sobie z tym poradzić?
Odpowiedzi:
4 dla odpowiedzi № 1To dlatego, że case
połączenia ===
, i ===
w klasie (a konkretnie moduł, z którego wywodzi się klasa) jest zaimplementowany w następujący sposób:
mod === obj
→true
lubfalse
Równość wielkości liter - zwroty
true
gdybyobj
jest instancjąmod
lub jeden zmod
Potomkowie. Ma ograniczone zastosowanie dla modułów, ale może być używany w instrukcjach case do klasyfikowania obiektów według klas.
Oznacza to, że dla każdej stałej z wyjątkiem Class
& Module
(na przykład. Foo
), Foo === Foo
zawsze wraca false
. W rezultacie zawsze otrzymujesz else
stan w twoim case
komunikat.
Zamiast tego po prostu zadzwoń case
z samym obiektem zamiast jego klasy lub use if
sprawozdania.
3 dla odpowiedzi № 2
Przekaż odwołanie do obiektu do metody, ponieważ w tle używa ona operatora ===, więc to się nie powiedzie. na przykład
obj = "hello"
case obj.class
when String
print("It is a string")
when Fixnum
print("It is a number")
else
print("It is not a string")
end
To z drugiej strony działa dobrze:
obj = "hello"
case obj # was case obj.class
when String
print("It is a string")
when Fixnum
print("It is a number")
else
print("It is not a string")
end
Zobacz odpowiednią odpowiedź na temat „Jak napisać instrukcję przełącznika w języku Ruby” https://stackoverflow.com/a/5694333/1092644
1 dla odpowiedzi nr 3
Możesz dodać to_s
do stałej klasy, jeśli chcesz tylko porównać równość nazw.
def my_method(class_name)
case class_name.to_s
when "Article"
make_a_thing
when "Comment"
make_another_thing
... ...
end
end