2012-04-03 11 views
5

Wie kann ich den Klassennamen einer Instanz von BasicObject in Ruby erhalten? Sagen wir zum Beispiel:Get Ruby Klassenname ohne Klassenmethode

class MyObjectSystem < BasicObject 
end 
puts MyObjectSystem.new.class 

Wie kann ich diesen Code erfolgreich machen?

BEARBEITEN: Ich habe festgestellt, dass Objekt Instanz Methode class als return rb_class_real(CLASS_OF(obj)); definiert ist. Irgendeine Möglichkeit, dies von Ruby zu verwenden?

+1

Können Sie geben etwas konkreteres Beispiel für das, was Sie versuchen zu tun? Fragen Sie: "Wenn ich eine Klasse Foo habe, die von BasicObject erbt, gibt es eine Möglichkeit zu identifizieren, dass eine Instanz dieser Klasse 'Foo' im Gegensatz zu BasicObject ist"? Nicht sicher, was du fragst. –

+0

Eigentlich ja genau! Ändern des Beitrags zur Klärung – Jwosty

+0

'MyObjectSystem.class.name'? –

Antwort

8

Ich verbrachte einige Zeit mit irb herumgespielt und kam mit dieser:

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 

, dass jedes Objekt geben wird, die von Basicobject eine #class Methode erbt, die Sie aufrufen können.

bearbeiten

Weitere Erklärungen wie in den Kommentaren angefordert:

Sagen Sie bitte Objekt obj haben, die eine Instanz der Klasse ist Foo. obj ruft seine Instanzmethoden von denen ab, die innerhalb der Klasse Foo definiert sind, zusätzlich zu den Methoden, die in der übergeordneten Klasse Foo usw. definiert sind, und so weiter die Vererbungskette. Ruby können Sie Methoden direkt auf ein Objekt definieren, wie diese

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

obj.hello #=> hello 

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

Der Grund, warum Sie dies tun können, um dieses Objekt nur zugänglich sind, weil jedes Objekt etwas ein Singleton-Klasse genannt hat (oder manchmal ein Eigenklasse nennen), dass Sie definieren die Methode tatsächlich. Diese Singleton-Klasse existiert tatsächlich in der Vererbungskette des Objekts direkt unter der tatsächlichen Klasse des Objekts. Das macht die tatsächliche Klasse des Objekts Foo in diesem Beispiel die Oberklasse der Singleton-Klasse des Objekts.

Die Zeile class << self, die Sie in der Antwort sehen, ist eine spezielle Syntax zum Eingeben des Gültigkeitsbereichs der Singleton-Klasse eines Objekts. So in dem obigen Beispiel könnte man auch ein Verfahren in einem Singleton-Klasse des Objekts definieren, wie diese

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

obj.goodbye #=> goodbye 

So ist die Linie class << self; self; end ist das Singleton Klasse des Objekts zu öffnen (was auch immer Objekt ist derzeit self) und dann self Rückkehr (self hat jetzt die Singleton-Klasse), die dann einer Variablen zugewiesen werden kann, um das zu tun, was Sie wünschen.

Ich würde empfehlen, Metaprogramming Ruby zu lesen, wenn Sie eine bessere Erklärung von all dem wollen. Es gibt Ihnen auf jeden Fall ein viel besseres Verständnis des Ruby-Objektmodells als Ganzes.

+0

Ah, vielen Dank! Dies scheint den Trick zu machen. – Jwosty

+3

Oh, das ist schlau! –

+0

Das ist großartig. Ich würde gerne verstehen, warum und wie das funktioniert. Könnten Sie eine ausführlichere Erklärung geben? –

1

Ich muss in ein paar Minuten gehen, damit ich es nicht selbst testen kann, aber es scheint, als könnten Sie ein separates Modul erstellen, das ffi verwendet, um rb_class_real von libruby aufrufen. Wenn ich mehr Zeit hätte, würde ich es zuerst testen, aber noch niemand hat geantwortet, und ich möchte nicht, dass du dich völlig in der Kälte zurücklässt.

+1

In Ordnung, ich werde das untersuchen. Vielen Dank! Aber kennst du einen reinen Ruby Weg? Das wäre wirklich nett. – Jwosty

0

Basierend auf Jeff Smith answer Sie diese BasicObject ohne Änderung tun können:

class << object; self; end.superclass 

wo object ist eine Instanz eines Objekts, dessen Klasse, die Sie wollen, das heißt,

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