2016-05-20 4 views
0

Der Titel Art von saugt, so diesen Code nehmen statt: „Foo“Anruf Super im Modul definierten Verfahren aus der Klasse erbt

module MyModule 
    def foo 
    puts "Foo!" 
    super if defined?(super) 
    end 
end 

class MyClass 
    include MyModule 
end 

class MySubclass < MyClass 
    include MyModule 
end 

Wenn ich die folgenden nennen, druckt einmal.

MySubclass.new.foo 
# Foo! 
# => nil 

Ich möchte es, indem Sie super durch den Aufruf der MySubclass eine erste, dann die MyClass 1 Sekunde zweimal, drucken.

Die MySubclass Herkunft wie folgt aussieht:

[MySubclass, MyClass, MyModule, Object, Kernel, BasicObject] 

Ich könnte Missverständnis, wie Rubin hat Klasse, Methode Abstammung, also, wenn dies nicht der richtige Weg, es zu tun ist, gibt es eine andere clevere Art und Weise dies zu erreichen?

BEARBEITEN: Okay, hört sich an, als müsste ich einen nützlicheren Anwendungsfall geben. Nehmen wir an, das Modul macht etwas wie ActiveRecord oder Mongoid, wo Sie ein Attribut deklarieren.

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

    module ClassMethods 
    attr_reader :fields 
    def field(name) 
     (@fields ||= []) << name.to_sym 
    end 
    end 
end 

Dann nutzen Sie, dass ein Feld in der Klasse und Unterklasse zu deklarieren:

class MyClass 
    include MyModule 
    field(:a) 
end 

class MySubclass < MyClass 
    include MyModule 
    field(:b) 
end 

Wenn Sie MySubclass.fields aufgerufen, ich will es nicht [:b] zurückkehren ich es [:a, :b] zurückkehren möchten, indem Sie fields auf seiner Elternklasse aufrufen und seine eigenen auf das Ergebnis verketten.

+0

Das Modul ist im Lieferumfang enthalten nur ein einziges Mal: ​​[ „Rubys Standardimplementierung ist die Konstanten hinzufügen , Methoden und Modulvariablen dieses Moduls zu _mod_, wenn dieses Modul noch nicht zu _mod_ ** oder einem seiner Vorgänger hinzugefügt wurde. ** "] (http://ruby-doc.org/core-2.3.1/ Module.html # method-i-append_features) Was ist Ihr Anwendungsfall, was möchten Sie erreichen? – matt

+0

Was Sie sagen, macht Sinn. Aber ich versuche immer noch, einen klugen Weg zu finden, um das Verhalten zu erreichen, das ich möchte. Ich habe oben einen anderen Anwendungsfall hinzugefügt. –

Antwort

1

Da diese Klasse Methoden sind, können Sie Art tun ein Ende laufen um sich Gedanken über super durch dies zu tun:

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

    module ClassMethods 
    def fields 
     (@fields || []) + (superlcass.respond_to?(:fields) ? superclass.fields : []) 
    end 
    def field(name) 
     (@fields ||= []) << name.to_sym 
    end 
    end 
end 
+0

Das ist mehr oder weniger genau das, was ich getan habe. –

Verwandte Themen