2013-02-08 5 views
5

Ich habe ein Modul mit Methoden, die in ein Protokoll schreiben. In jede Nachricht möchte ich den Namen der Klasse eintragen, die diese Nachricht protokolliert hat. Das Modul kann unter Verwendung von include oder extend gemischt werden. Ich brauche mein Protokoll, um in jedem Fall korrekte Klassennamen zu haben.self.class.name in einem Mix-in-Modul

Destilliertes Code:

module M 
    def f 
    self.class.name 
    end 
end 

class C 
    extend M 
    include M 
end 

p C.f # => "Class" 
p C.new.f # => "C" 

Wie Sie der erste Aufruf zu sehen, druckt falsch "Class". Ich möchte, dass es auch "C" ist.

Wie wird das erreicht?

Antwort

4

Keine Notwendigkeit, Haken greifen, einfach Ihr Verhalten ändern, wenn self ein Class/Module ist:

module M 
    def f 
    self.is_a?(Module) ? name : self.class.name 
    end 
end 

class C 
    extend M 
    include M 
end 

C.f  #=> "C" 
C.new.f #=> "C" 
3

Sie können es so tun, weiß nicht, ob eine bessere Methode existiert.

module M 
    def self.included(base) 
    base.extend ClassMethods 
    end 

    def f 
    self.class.name 
    end 

    module ClassMethods 
    def f 
     self.name 
    end 
    end 
end 

class C 
    include M 
end 
+0

Dies funktioniert allerdings nicht, wenn Sie 'M' verlängern, though. –

+0

Sie müssen nicht erweitern. Die Methoden, die Sie in Klassenmethoden umwandeln möchten, die Sie in das ClassMethods-Modul einfügen. :) – Kaeros

+0

Was ist, wenn ich nur erweitern und nicht einschließen möchte? Dann muss ich 'M: ClassMethods' aus gutem Grund verlängern. Persönlich mag ich das ganze Ausdehnungs-Einschluss-Muster auch nicht wirklich. –

Verwandte Themen