2012-04-03 4 views
5

Jak mogę uzyskać nazwę klasy instancji BasicObject w Ruby? Na przykład powiedz: Mam to:Uzyskaj nazwę klasy Ruby bez metody klasy

class MyObjectSystem < BasicObject 
end 
puts MyObjectSystem.new.class 

Jak mogę uczynić ten kod sukcesem?

EDYCJA: Odkryłem, że metoda instancji obiektu class jest zdefiniowana jako return rb_class_real(CLASS_OF(obj));. Jakikolwiek sposób użyć tego z Ruby?

+1

można dać nieco bardziej konkretny przykład tego, co próbujesz zrobić? Pytasz "Jeśli mam klasę Foo, która dziedziczy po BasicObject, czy istnieje sposób na określenie, że instancją tej klasy jest" Foo "w przeciwieństwie do BasicObject"? Nie jestem pewien, o co pytasz. –

+0

Właściwie, tak dokładnie! Zmiana postu w celu wyjaśnienia: – Jwosty

+0

'MyObjectSystem.class.name'? –

Odpowiedz

8

Spędziłem trochę czasu gry z IRB i podszedł z tym:

class BasicObject 
    def class 
    klass = class << self; self; end # get the object's singleton class 
    klass.superclass # the superclass of an object's singleton class is that object's class 
    end 
end 

To da dowolny obiekt, który dziedziczy BasicObject się #class metody, które można nazwać.

Edit

Dalsze wyjaśnienia na żądanie w komentarzach:

Powiedzmy, że masz obiekt obj który jest instancją klasy Foo. obj pobiera metody instancji od tych, które są zdefiniowane w klasie Foo, oprócz metod zdefiniowanych w klasie nadrzędnej Foo i tak dalej w łańcuchu dziedziczenia. Ruby pozwala definiować metody bezpośrednio na obiekcie, które są dostępne tylko dla tego konkretnego obiektu jak ten

obj = Foo.new 
def obj.hello 
    puts "hello" 
end 

obj.hello #=> hello 

other_obj = Foo.new 
other_obj.hello #=> Method missing error 

Powodem można to zrobić, ponieważ każdy przedmiot ma coś, co nazywa klasą Singleton (lub czasami nazywamy eigenclass), które faktycznie określasz metodę na. Ta klasa singletona faktycznie istnieje w łańcuchu dziedziczenia obiektu bezpośrednio pod rzeczywistą klasą obiektu. To czyni klasę rzeczywistą obiektu, Foo w tym przykładzie, nadklasą klasy singleton obiektu.

Wiersz class << self, który widzisz w odpowiedzi, to specjalna składnia do wprowadzania zakresu pojedynczej klasy obiektu. Tak więc w powyższym przykładzie, można również zdefiniować metodę w Singleton klasy obiekt wygląda tak

class << obj 
    def goodbye 
    puts "goodbye" 
    end 
end 

obj.goodbye #=> goodbye 

więc linia class << self; self; end otwiera klasę singleton obiektu (cokolwiek obiekt jest obecnie self), a następnie powrocie self (self ma teraz stają się klasą singleton), które można następnie przypisać do zmiennej, aby robić to, co chcesz.

Polecam lekturę Metaprogramming Ruby, jeśli chcesz uzyskać lepsze wyjaśnienie tego wszystkiego. To zdecydowanie daje dużo lepsze zrozumienie modelu obiektu Ruby jako całości.

+0

Ah, dzięki za banda! Wydaje się, że to wystarczy. – Jwosty

+3

O, to jest mądre! –

+0

To jest niesamowite. Chciałbym zrozumieć, dlaczego i jak to działa. Czy możesz podać bardziej szczegółowe wyjaśnienie? –

1

Muszę wyjść w ciągu kilku minut, więc nie mogę go przetestować samodzielnie, ale wygląda na to, że można stworzyć osobny moduł, który używa ffi do wywoływania rb_class_real z libruby. Gdybym miał więcej czasu, najpierw przetestowałbym to, ale nikt jeszcze nie odpowiedział i nie chcę, żebyś zostawił cię całkowicie na mrozie.

+1

Dobra, przyjrzę się temu. Dzięki! Ale czy znasz czysty sposób Ruby? To byłoby naprawdę miłe. – Jwosty

0

podstawie Jeff Smith answer, można to zrobić bez modyfikowania BasicObject:

class << object; self; end.superclass 

gdzie object jest instancją obiektu, którego klasa chcesz, tj

irb(main):001:0> object = BasicObject.new 
(Object doesn't support #inspect) 
=> 
irb(main):002:0> class << object; self; end.superclass 
=> BasicObject