2013-09-05 2 views
4

Я не уверен, что объект, передаваемый методу, имеет правильный тип. Я могу передать строку функции, которая может обрабатывать только целые числа. Как насчет какой-то гарантии времени выполнения? Я не видел лучшего варианта, чем:Проверка типа параметра метода

def someFixNumMangler(input) 
    raise "wrong type: integer required" unless input.class == FixNum 
    other_stuff 
end 

Любые лучшие альтернативы?

+0

Я согласен с настроением. Общий подход, который я придерживаюсь, заключается в том, чтобы выполнить минимальную проверку, чтобы избежать * странных, бесполезных * ошибок (или Segfaults при работе с расширениями C), которые возникают позже при использовании общедоступного API библиотеки. Тип защитного программирования, который вы получаете, проверяя типы по всем методам, в Ruby не очень практичен. Вы можете покрыть некоторые пробелы в тестах и ​​документации, оба из которых * хорошо поддерживаются. –

ответ

5

Используйте метод Kernel#Integer для преобразования ввода перед его использованием. Он поднимет ArgumentError, когда вход не может быть преобразован в целое число любым разумным способом.

def my_method(number) 
    number = Integer(number) 
    # do something with number, which is now guaranteed to be an integer 
end 

Я рекомендую новую книгу AVDI Гримм Confident Ruby для большего понимания этого.

+0

действительно, но изначально (до того, как он был отредактирован) мой вопрос был шире, касаясь общих объектов. для объектов, которые я определил, я должен написать свой собственный метод для проверки ... – Miotsu

+1

Да, ваш собственный метод преобразования, который обрабатывает все мыслимые данные и создает правильные ошибки времени выполнения, - это путь. –

3

Если вам действительно нужно выполнять проверки типов, то да, вы проверяете только время выполнения. Код в вопросе в порядке. Вы также можете использовать .is_a?.

def someFixNumMangler(input) 
    raise "wrong type: integer required" unless input.is_a?(FixNum) 
    other_stuff 
end 

Проверки могут иметь разные формы. Если вы ожидаете, скажем, строки, и вы вызываете на ней строковые методы (upcase, gsub и т. Д.), Код взорвется, если передается что-либо, кроме строки. Если, конечно, вы не передаете объект, который не является строкой, а ведет себя точно так же, как один (имеет те же методы, которые вы называете). В этом суть утиной печати.

Что делать, если ваш метод выглядит так?

def someFixNumMangler(input) 
    input = input.to_i 
    puts "got this: #{input} of #{input.class}" 
end 


someFixNumMangler(10) 
someFixNumMangler('42') 
someFixNumMangler(File) 

# >> got this: 10 of Fixnum 
# >> got this: 42 of Fixnum 
# ~> -:2:in `someFixNumMangler': undefined method `to_i' for File:Class (NoMethodError) 
# ~> from -:9:in `<main>' 

Пока аргумент отвечает #to_i, вы на самом деле не волнует, что его тип.

+1

Я думаю, что повышение 'TypeError' является более подходящим. – toro2k

+0

@ toro2k: да, но вот детали –