Проверить, является ли переменная строкой в ​​Ruby

Ответы:

206

Я думаю вы ищите instance_of?. is_a?и kind_of?вернет true для экземпляров из производных классов.

class X < String
end

foo = X.new

foo.is_a? String         # true
foo.kind_of? String      # true
foo.instance_of? String  # false
foo.instance_of? X       # true
Кандид
источник
9
Не зная смысла вопроса, я бы сказал, что для большинства реальных программных ситуаций is_a?это более подходящая идиома для использования (и часто проверка типа «утка», как упоминает Эндрю Гримм, даже лучше). Строгое сравнение классов - это обычно запах кода. en.wikipedia.org/wiki/Liskov_substitution_principle
mahemoff
Небольшое отступление: если вы используете это в условной логике, вам нужно использовать круглые скобки; например, если foo.is_a? (String) && ...
дан
Как и следовало ожидать, этот подход будет работать не только с String, но и с Integerи Float. Это тоже работает Decimal? (превосходный интерпретатор текста по-разному выделяет синтаксис, Decimalчто вызывает у меня подозрение)
стивек
29

Более типичный подход - сказать

foo.respond_to?(:to_str)

to_str указывает, что класс объекта не может быть фактическим потомком String, но сам объект очень похож на строку (тягучий?).

Эндрю Гримм
источник
Прохладно. В этом случае я знаю , что fooбудет либо true, falseили строка ванили, но это хорошо , чтобы узнать более общие решения.
davidchambers
объедините это с вызовом to_s после проверки, отвечает ли объект ему, и вы получите строку!
seanmakesgames
1
@seanmakesgames Вы имели в виду to_str, или to_s? Эти два немного отличаются.
Эндрю Гримм
stackoverflow.com/questions/11182052/… Re: комментарий Эндрю.
seanmakesgames 01
23

Ты можешь сделать:

foo.instance_of?(String)

И более общее:

foo.kind_of?(String)
Федерико Булес
источник
4
Что делает kind_ofболее общим? Они кажутся синонимами: is_a.
davidchambers
2
@Davidchambers, ты прав, kind_of? является синонимом «is_a?».
steenslag
@davidchambers: Вы правы, я имел в виду instance_of?вместо is_a?.
Федерико Байлс,
7
foo.instance_of? String

или

foo.kind_of? String 

если вас интересует только то, получено ли оно откуда- Stringто из цепочки наследования

Мэтью
источник
4

В дополнение к другим ответам Class определяет метод === для проверки того, является ли объект экземпляром этого класса.

  • o.class класс o.
  • o.instance_of? c определяет, является ли o.class == c
  • o.is_a? c Является ли o экземпляром c или любого из его подклассов?
  • o.kind_of? c синоним для * is_a? *
  • c === o для класса или модуля, определите, есть ли * o.is_a? c * ( String === "s" возвращает истину)
steenslag
источник
-1

Я думаю, что лучший способ - создать несколько методов предиката. Это также сохранит вашу «Единую точку контроля».

class Object
 def is_string?
   false
 end
end

class String
 def is_string?
   true
 end
end

print "test".is_string? #=> true
print 1.is_string?      #=> false

Более утиный способ набора текста;)

schlegel11
источник
2
что не так "string".is_a?(String). Кажется, ты изобретаешь велосипед. Там же class, instance_of, kind_ofи т.д. ... Плохая идея для обезьяны патча Objectкласса, не говоря уже о его излишен.
Мохамад
Я полностью согласен с вами :) Если ваше внимание сосредоточено только на примитивных типах и вы знаете, что требования вашего проекта, связанные с примитивными типами, никогда не изменятся (хорошо, обычно это так;)), то все в порядке. Но в случае, если требования меняются, лучше иметь «Единую точку контроля». Например, в среде вашего проекта у вас есть много предварительных проверок (от 1000 и выше). pre_check("test".is_string?) Теперь требования к вашему проекту изменится, и каждая строка из трех или более символов больше не определяется как строка (я знаю, что это необычно;)) Теперь вы можете легко изменить свой собственный метод.
schlegel11