2017-06-05 4 views
-2

Es ist möglich, Methoden zu einer Klasse mit Modulen hinzuzufügen. ZBRuby-Module für Funktionen

Ist es möglich, das gleiche mit Methoden zu tun? ZB

class Test 
    include Singleton 

    def test 
    include Instructions_to_add_to_the_method 
    puts 'done' 
    end 
end 

wo:

module Instructions_to_add_to_the_method 
    puts 'hi !' 
end 

Wenn Test.instance.test anrufen, ich will:

hi ! 
done 

Ich möchte nicht eine andere Methode nennen, da es mir Probleme mit dem Umfang geben würde, meiner Variablen.

+0

Nein, so funktioniert Ruby nicht. Module sind keine Makros. Sie könnten 'Module # prepend' oder' Module # include' in Verbindung mit 'super' verwenden, wenn Sie das erreichen möchten? –

Antwort

1

Es ist möglich, hinzufügen Methoden zu einer Klasse mit Modulen. Z. B.

class Test 
    include Singleton 
end 

Nr Dieser „Hinzufügen von Methoden zu einer Klasse“ nicht. include macht einfach Singleton die Oberklasse von Test. Nichts mehr. Nichts wird "zu einer Klasse hinzugefügt". Es ist nur Vererbung.

Ist es möglich, dasselbe mit Methoden zu tun? Z. B.

class Test 
    include Singleton 

    def test 
    include Instructions_to_add_to_the_method 
    puts 'done' 
    end 
end 

Es gibt keine Methode Test#include, so wird dies einfach raise ein NoMethodError.

class Test 
    include Singleton 

    def test 
    super 
    puts 'done' 
    end 
end 

module Instructions_to_add_to_the_method 
    def test 
    puts 'hi' 
    end 
end 

class Test 
    include Instructions_to_add_to_the_method 
end 

Test.instance.test 
# hi 
# done 

Hinweis

dass auf diese Weise Vererbung in Ruby verwenden rückwärts ein wenig ist:

Wenn Test.instance.test anrufen, ich will:

hi ! 
done 

Das ist, was für die Vererbung ist. Wenn Sie so etwas wirklich brauchen, sollten Sie eine Sprache wie Beta verwenden, wo Vererbung auf natürliche Weise funktioniert.

Eine bessere Lösung wäre so etwas wie die Template Method Software Design Pattern sein, die in Ruby können zu einem Block ing etwas so einfache wie yield sein:

class Test 
    include Singleton 

    def test 
    yield 
    puts 'done' 
    end 
end 

Test.instance.test { puts 'hi' } 
# hi 
# done 

oder nimm ein Proc als Argument:

class Test 
    include Singleton 

    def test(prc) 
    prc.() 
    puts 'done' 
    end 
end 

Test.instance.test(-> { puts 'hi' }) 
# hi 
# done 

oder indem eine Hook-Methode aufgerufen wird:

class Test 
    include Singleton 

    def test 
    extension_hook 
    puts 'done' 
    end 

    def extension_hook; end 
end 

class HookedTest < Test 
    def extension_hook 
    puts 'hi' 
    end 
end 

HookedTest.instance.test 
# hi 
# done 

Ich möchte nicht eine andere Methode aufrufen, da es Probleme mit dem Umfang meiner Variablen geben würde.

Es gibt keine Variablen in Ihrem Code, daher kann es keine "Probleme" mit ihnen geben.

+0

vielen Dank für die Antwort, es scheint, dass mein Verständnis der Vererbung der Ruby-Klasse ein wenig aus war –

1

Dies ist wahrscheinlich eine schreckliche Idee. Wenn Sie zur Laufzeit mit Ihren Klassen rumspielen, wird es schwierig, Probleme zu debuggen (welche Version dieser Methode habe ich dort aufgerufen?) Und Ihr Code ist schwer zu befolgen (oh, richtig, ich kann diese Methode noch nicht aufrufen, weil sie noch nicht definiert ist) , Muss ich diese Methode zuerst nennen).

In Anbetracht dessen, was Sie am Ende Ihrer Frage zum Variablen-Scoping gesagt haben, bin ich mir fast sicher, dass dies das Problem, das Sie tatsächlich haben, nicht löst, und ich würde vorschlagen, Ihr tatsächliches Problem zu veröffentlichen.

Das heißt, die Frage, die Sie durch die Verwendung der included und extended Haken beantwortet werden gebeten, können die, wenig überraschend, Feuer, wenn ein Modul enthalten und erweitert wird:


module FooModule 
    def self.included(base) 
    puts 'FooModule included' 
    end 

    def self.extended(base) 
    puts 'FooModule extended' 
    end 
  
    def new_method 
    puts 'new method called' 
    end 
end 

class Extender 
    def test_extend 
    self.extend FooModule 
    puts 'done' 
    end 
end 

class Includer 
    def test_include 
    self.class.include FooModule 
    puts 'done' 
    end 
end 

t1 = Extender.new 
t2 = Extender.new 
t1.test_extend # Prints out "FooModule extended" followed by "done" 
t1.new_method # Prints out "new method called" 
t2.new_method rescue puts 'error' # Prints out "error" - extend only modifies the instance that calls it 

t1 = Includer.new 
t2 = Includer.new 
t1.test_include # Prints out "FooModule included" followed by "done" 
t1.new_method # Prints out "new method called" 
t2.new_method # Prints out "new method called" - all past and future instances of Includer have been modified