Określanie typu obiektu w rubinie


364

Użyję Pythona jako przykładu tego, czego szukam (możesz myśleć o tym jak o pseudokodzie, jeśli nie znasz Pythona):

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

Wiem, że w rubinie mogę:

1.9.3p194 :002 > 1.class
 => Fixnum 

Ale czy jest to właściwy sposób na określenie rodzaju obiektu?


5
@ JörgWMittag AFAICR To właśnie robi `type` w Pythonie, chociaż moja pamięć jest rozmyta. Będziesz potrzebować isinstance lub sprawdzać odpowiedzi. Ale po prostu mówiąc „NIE !!!” nie jest naprawdę pomocny, prawda? Zamiast tego rozważ edukację.
Dave Newton

4
@ JörgWMittag Podczas gdy jestem sympatyczny, OP zapewnił kod do naśladowania w Ruby. Chyba, że faktycznie wychowywać PO mówiąc sieci doskonałości nie jest pomocne, IMO. I nawet gdybyś to zrobił, prawdopodobnie byłby to tylko informacyjny, ponieważ OP zdefiniował, czego chce przez kod.
Dave Newton,

5
@ JörgWMittag - w Rubim wszystko jest Obiektem, więc nie ma prymitywnych typów, jak w Pythonie (int, long, boolean itp.) W rezultacie w Ruby klasy są definicjami typów. Nie jest to również ograniczone do Ruby, słowo klasa i typ są synonimami w kilku innych językach, a szerzej w teorii OOP.
ocodo

6
Ponieważ tak naprawdę mówimy tutaj o Ruby, typy i klasy są synonimami, nie ma o tym debaty, wszystkie wartości są Przedmiotami. Więc dla każdego, kto mówi po prostu o Ruby, klasy typami. - ref: ruby-lang.org/en/about
ocodo

2
@ JörgWMittag Ten esej jest jak dotąd dość pouczający, a resztę przeczytam, kiedy będę miał szansę. W szczególności Cook wydaje się dość dobrze artykułować (i mając dużo większą wiedzę niż ja), dlaczego błędne jest twierdzenie (jak zrobił to jeden z moich profesorów), że Python, Ruby i inne dynamicznie pisane języki „nie są tak naprawdę przedmiotem -oriented ”(co prawdopodobnie miał na myśli, nie zdając sobie z tego sprawy, że nie byli zorientowani na ADT). Ale Ruby nie jest wpisywana statycznie, więc nie ma ADT w znaczeniu opisanym przez Cooka, więc twoje zastrzeżenia na podstawie tego rozróżnienia nie są pomocne.
Kyle Strand

Odpowiedzi:


607

Właściwym sposobem określenia „typu” obiektu, który jest niestabilnym terminem w świecie Ruby, jest wywołanie object.class.

Ponieważ klasy mogą dziedziczyć po innych klasach, jeśli chcesz ustalić, czy obiekt jest „określonego typu”, możesz wywołać, object.is_a?(ClassName)aby sprawdzić, czy objectjest on typu, ClassNameczy pochodzi z niego.

Zwykle sprawdzanie typów nie jest wykonywane w Rubim, ale obiekty są oceniane na podstawie ich zdolności do reagowania na określone metody, zwane potocznie „ Typowaniem kaczym ”. Innymi słowy, jeśli odpowiada on wybranym metodom, nie ma powodu, aby zwracać szczególną uwagę na ten typ.

Na przykład object.is_a?(String)jest zbyt sztywny, ponieważ inna klasa może zaimplementować metody, które przekonwertują go na ciąg znaków lub sprawią, że będzie on zachowywał się identycznie jak łańcuch. object.respond_to?(:to_s)byłby lepszym sposobem sprawdzenia, czy dany obiekt robi to, co chcesz.


13
-1. #classnie nie zwraca typ obiektu, zwraca swoją klasę . Nazwa powinna być martwym prezentem. Klasa i typ to dwie zupełnie różne koncepcje w OO.
Jörg W Mittag

78
@ Jörg W Mittag: Nie zgadzam się. „Klasa” i „szybkość procesora” (aby wybrać przykład) to dwie zupełnie różne koncepcje, ale „klasa” i „typ” są ściśle powiązanymi pojęciami. Oto na przykład następujący artykuł Wikipedii na temat klasy : „W programowaniu obiektowym klasa jest konstrukcją służącą do definiowania odrębnego typu”. tadman był pomocny dla pytającego.
Teemu Leisti

18
@ JörgWMittag W Ruby najbliższą rzeczą typeofod C, JavaScript i innych jest class. W Rubim nie ma formalnego systemu protokołów, tak jak w innych językach, a Objective-C jest najbliższym spokrewnionym z nim językiem. Jeśli definiujesz „typ” jako „obiekt, który reaguje na określony zestaw metod z akceptowalnymi wynikami”, to tak naprawdę nie ma sposobu, aby to potwierdzić. Jest po prostu zbyt luźny. Przez większość czasu w Rubim, gdy mowa jest o typie obiektu, zrozumiałe jest, że mówisz o klasie. Właśnie z tego powodu użyłem tego typu w cudzysłowie.
tadman

14
@ Jörg W Mittag: Kontynuuję twierdzenie, że „klasa” i „typ” z pewnością nie są całkowicie różnymi koncepcjami w OO, jak pokazuje cytat. (Również: w jaki sposób zadeklarować zmienną w Javie Dając? Albo ten typ lub klasę zmiennej, a następnie jego imię: „ int i” lub „ Integer j”). Tadman odpowiedział na pytanie w sposób, który zdawał się spełniać zarówno pytającego oraz publiczność, wyjaśniając jednocześnie terminologię, której używa Ruby. Nie interesuje mnie rozwiązywanie kwestii akademickich na temat drobniejszych aspektów terminologii zorientowanej obiektowo, więc proszę o ostatnie słowo.
Teemu Leisti

11
@TeemuLeisti Większość problemów tutaj wynika z faktu, że wszystko w Ruby jest przedmiotem, podobnie jak klasa, podczas gdy w praktycznie każdym innym języku istnieją prymitywne typy, które nie są obiektami i nie mają klasy, w przeciwieństwie do obiektów, które to robią. Kiedy nie ma czegoś takiego jak czysty typ i nie ma możliwości formalnego zdefiniowania jednego, znaczenie staje się szczególnie mgliste w świecie Ruby. Matz nie przestrzega ściśle żadnej konkretnej szkoły myślenia tutaj innej niż jego własna.
tadman

81

możesz także spróbować: instance_of?

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

44

Często w Ruby nie obchodzi cię, czym jest klasa obiektu, po prostu zależy ci, żeby zareagował na określoną metodę. Jest to znane jako Pisanie kaczek i zobaczysz je we wszystkich bazach kodu Ruby.

Tak więc w wielu (jeśli nie w większości) przypadkach najlepiej jest używać Duck Typing, używając #respond_to?(method):

object.respond_to?(:to_i)

1
ważny punkt. nie odpowiada na pytanie, ale uderza w ducha pytania.
user566245,

@ user566245 no odpowiada to_to? (: the_question), ale tak jak powiedziałeś, to nie odpowiada na pytanie, po prostu podaje powiązane informacje. Bardzo pewne odpowiedzi muszą odpowiedzieć na pytanie.
R. Rincón

17

Powiedziałbym tak". Jak powiedział „Matz” w jednym ze swoich wystąpień: „Obiekty Ruby nie mają typów”. Nie wszystko, ale część, którą próbuje nam przekazać. Dlaczego więc ktoś powiedziałby „wszystko jest przedmiotem”? Aby dodać, powiedział: „Dane mają typy, a nie obiekty”.

Więc możemy się tym cieszyć.

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

Ale Ruby nie przejmuje się zbytnio typem obiektu, tylko klasą. Używamy klas, a nie typów. Wszystkie dane mają wtedy klasę.

12345.class

'my string'.class

Mogą mieć także przodków

Object.ancestors

Mają też meta-klasy, ale oszczędzę ci szczegółów na ten temat.

Gdy poznasz klasę, będziesz w stanie sprawdzić, jakich metod możesz użyć. Właśnie tam potrzebny jest „typ danych”. Jeśli naprawdę chcesz poznać szczegóły, sprawdź ...

„Rubinowy model obiektowy”

Jest to termin używany do tego, jak Ruby obsługuje obiekty. Wszystko jest wewnętrzne, więc tak naprawdę nie widać zbyt wiele, ale dobrze jest wiedzieć. Ale to inny temat.

Tak! Klasa jest typem danych. Obiekty mają klasy, a dane mają typy. Jeśli więc wiesz o bazach danych, to wiesz, że istnieje tylko skończony zestaw typów.

liczby bloków tekstu


Na przykładObject.ancestors # => [Object, Kernel, BasicObject]
Dorian
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.