Determinando o tipo de um objeto em ruby

365

Vou usar python como um exemplo do que estou procurando (você pode pensar nisso como pseudocódigo, se não conhece o Python):

>>> a = 1
>>> type(a)
<type 'int'>

Eu sei em ruby ​​que posso fazer:

1.9.3p194 :002 > 1.class
 => Fixnum 

Mas esta é a maneira correta de determinar o tipo do objeto?

Zippy Zeppoli
fonte
5
@ JörgWMittag No entanto, o AFAICR é o que o `type` faz no Python, embora minha memória seja confusa. Você precisaria isinstance ou procuraria por respostas. Mas simplesmente dizendo "NÃO !!!" não é realmente útil, agora, é? Em vez disso, considere ser educacional.
Dave Newton
4
@ JörgWMittag Embora eu seja solidário, o OP forneceu código para imitar no Ruby. A menos que você realmente instrua o OP dizendo não, não é útil, IMO. E mesmo que você o fizesse, provavelmente seria apenas informativo, já que o OP definiu o que ele / ela queria através do código.
Dave Newton
5
@ JörgWMittag - no Ruby tudo é um Objeto, portanto não há tipos primitivos como existem no Python (int, long, booleano etc.) Como resultado, no Ruby, as classes são definições de tipo. Isso também não se limita ao Ruby, a palavra classe e tipo são sinônimos em vários outros idiomas e mais amplamente na teoria OOP.
Ocodo 03/03
6
Como estamos realmente falando sobre Ruby aqui, Tipos e Classes são sinônimos, não há debate sobre isso, todos os valores são Objetos. Portanto, para quem simplesmente fala sobre Ruby, Classes são Types. - ref: ruby-lang.org/pt/about
ocodo
2
@ JörgWMittag Esse ensaio é bastante informativo até agora, e vou ler o resto quando tiver uma chance. Em particular, Cook parece articular muito bem (e com muito mais conhecimento do que eu tenho) por que é incorreto afirmar (como um de meus professores fez) que Python, Ruby e outras linguagens dinamicamente "não são realmente objetivas -oriented "(o que ele provavelmente quis dizer, sem perceber, era que eles não eram orientados ao ADT). Mas Ruby não é digitado estaticamente, portanto, não possui ADTs no sentido em que Cook está descrevendo; portanto, suas objeções com base nessa distinção não são úteis.
Kyle Strand

Respostas:

608

A maneira correta de determinar o "tipo" de um objeto, que é um termo vacilante no mundo Ruby, é chamar object.class.

Como as classes podem herdar de outras classes, se você deseja determinar se um objeto é "de um tipo específico", você pode ligar object.is_a?(ClassName)para ver se objecté do tipo ClassNameou é derivado dele.

Normalmente, a verificação de tipo não é feita no Ruby, mas os objetos são avaliados com base em sua capacidade de responder a métodos específicos, comumente chamados de " digitação de pato ". Em outras palavras, se ele responder aos métodos desejados, não há razão para ser específico sobre o tipo.

Por exemplo, object.is_a?(String)é muito rígido, já que outra classe pode implementar métodos que a convertem em uma string ou fazer com que ela se comporte de maneira idêntica à maneira como a String se comporta. object.respond_to?(:to_s)seria uma maneira melhor de testar se o objeto em questão faz o que você deseja.

tadman
fonte
13
-1. #classse não retornar o tipo do objeto, ele retorna a sua classe . O nome deve ser uma oferta inoperante. Classe e Tipo são dois conceitos completamente diferentes no OO.
Jörg W Mittag 02/04
78
@ Jörg W Mittag: Eu discordo. "Classe" e "velocidade do processador" (para escolher um exemplo) são dois conceitos completamente diferentes, mas "classe" e "tipo" são conceitos intimamente relacionados. Por exemplo, eis o que o artigo da Wikipedia sobre Class diz: "Na programação orientada a objetos, uma classe é uma construção usada para definir um tipo distinto". tadman estava sendo útil para o interlocutor.
Teemu Leisti
18
@ JörgWMittag Em Ruby, a coisa mais próxima de typeof de C, JavaScript e outras é class. Não existe um sistema formal de protocolo em Ruby, como em outros idiomas, o Objective-C é o parente mais próximo do Smalltalk. Se você está definindo "tipo" como "objeto que responde a um conjunto específico de métodos com resultados aceitáveis", não há realmente nenhuma maneira de afirmar isso. É muito solto. Na maioria das vezes em Ruby, quando se refere ao tipo de um objeto, entende-se que você está falando sobre a classe. Eu usei o termo type entre aspas por esse mesmo motivo.
Tadman
14
@ Jörg W Mittag: Continuo afirmando que "classe" e "tipo" certamente não são conceitos completamente diferentes em OO, como demonstrado pela citação. (Também: como você declarar uma variável em Java Ao dar? Quer o tipo ou a classe da variável, seguido pelo seu nome: " int i" ou " Integer j".) Tadman respondeu à pergunta de uma maneira que parecia satisfazer tanto o questionador e o público em geral, esclarecendo a terminologia que Ruby usa. Não tenho interesse em dividir o cabelo acadêmico sobre os pontos mais delicados da terminologia orientada a objetos; portanto, tenha a última palavra.
Teemu Leisti
11
@TeemuLeisti A maioria dos problemas aqui vem do fato de que tudo em Ruby é um objeto e, portanto, tem uma classe, enquanto em praticamente todas as outras línguas existem tipos primitivos que não são objetos e não têm classe, em contraste com os objetos que o fazem. Quando não existe um tipo puro e não há maneira de defini-lo formalmente, o significado se torna especialmente nebuloso no mundo do Ruby. Matz não está aderindo estritamente a nenhuma escola particular de pensamento aqui além da sua.
precisa saber é
81

você também pode tentar: instance_of?

p 1.instance_of? Fixnum    #=> True
p "1".instance_of? String  #=> True
p [1,2].instance_of? Array #=> True
Arup Rakshit
fonte
44

Muitas vezes, em Ruby, você realmente não se importa com a classe do objeto, por si só, apenas se importa com a resposta a um determinado método. Isso é conhecido como Duck Typing e você verá em todos os tipos de bases de código Ruby.

Portanto, em muitos casos (se não na maioria), é melhor usar o Duck Typing usando #respond_to?(method):

object.respond_to?(:to_i)
Stuart M
fonte
11
ponto válido. não responde à pergunta, mas atinge o espírito da pergunta.
User566245 23/09/2015
@ user566245 bem, ele responde_ a? (: the_question), mas como você disse que não responde à pergunta, apenas fornece informações relacionadas. As respostas bastante certas precisam responder à pergunta.
R. Rincón
17

Eu diria "sim". Como "Matz" havia dito algo assim em uma de suas palestras, "objetos Ruby não têm tipos". Nem tudo, mas a parte que ele está tentando nos transmitir. Por que alguém teria dito "Tudo é um Objeto" então? Para adicionar, ele disse: "Os dados têm tipos, não objetos".

Então, podemos aproveitar isso.

https://www.youtube.com/watch?v=1l3U1X3z0CE

Mas Ruby não se importa muito com o tipo de objeto, apenas a classe. Usamos classes, não tipos. Todos os dados têm uma classe.

12345.class

'my string'.class

Eles também podem ter antepassados

Object.ancestors

Eles também têm meta-classes, mas eu vou salvar os detalhes sobre isso.

Depois de conhecer a classe, você poderá pesquisar quais métodos você pode usar para ela. É aí que o "tipo de dados" é necessário. Se você realmente quer entrar em detalhes, procure ...

"O modelo de objeto Ruby"

Este é o termo usado para como o Ruby lida com objetos. É tudo interno, então você realmente não vê muito disso, mas é bom saber. Mas esse é outro tópico.

Sim! A classe é o tipo de dados. Os objetos têm classes e os dados têm tipos. Portanto, se você conhece as bases de dados, sabe que há apenas um conjunto finito de tipos.

blocos de texto números

Douglas G. Allen
fonte
Por exemplo,Object.ancestors # => [Object, Kernel, BasicObject]
Dorian