2017-07-06 15 views
0

私は2つのモジュールを持っていて、どちらも関数 'foo'を持っているとします。それを含むクラスのオブジェクトを使用してModule1のfooを呼び出す必要がある場合、どのように呼び出す必要がありますか?クラスオブジェクトを使ってモジュール内のメソッドを呼び出す方法(別の2つのモジュールで同じメソッド名) - ruby​​

コードサンプル:

module Module1 
     def foo 
     puts 'first one' 
     end 
    end 

    module Module2 
     def foo 
     puts 'second one' 
     end 
    end 



    class ClassName 
     include Module1 
     include Module2 

     def initialize 
     Module1.instance_method(:foo).bind(self).call 
     Module2.instance_method(:foo).bind(self).call 
     end 
    end 

    cls = ClassName.new 

がどのようにメソッドを呼び出すオブジェクトのCLSを '(私はModule1のののfooを呼び出す必要がある場合)を使用して、FOO?

ありがとうございます!

+5

[XY問題](https://meta.stackexchange.com/q/66377)のようです。あなたは何を達成しようとしていますか? – Stefan

+0

あなたの質問は不明です。あなたはあなたの問題を解決したようです: 'initialize'メソッドの2つの行は、それぞれのメソッドを順に呼び出します。後で、またはクラスの外から電話する方法を尋ねていますか? –

+0

@JordanRunning。はい、ヨルダン。私はクラス内のメソッドを呼び出すことができます。しかし、私はクラスの外でクラスオブジェクトを使用して呼び出したい。 – user3763227

答えて

2

あなたが通常のインスタンスメソッドのセマンティクスを維持したい場合は、最も簡単な解決策は、あなたの前にちょうど方法に別名おそらくinclude第二のモジュール:

class ClassName 
    include Module1 
    alias :module_1_foo :foo 
    include Module2 
end 

cls = ClassName.new 
cls.module_1_foo 
# => first one 
cls.foo 
# => second one 

repl.itでそれを参照してください:https://repl.it/JQ73

はまた、あなたはdefine_methodModule1.instance_method(:foo)によって返さUnboundMethodオブジェクトを渡すことができます。

class ClassName 
    include Module1 
    include Module2 
    define_method(:module_1_foo, Module1.instance_method(:foo)) 
end 

これらの両方の注意点は、Module1にfooを呼び出す他のインスタンスメソッドがある場合、Module2#fooを呼び出して終了することです。彼らはMethod1#fooが「名前が変更されました」ということを知る方法がありません。これはせいぜい停止の余地があります。コードに複雑さがある場合は、名前の衝突がないように全体を再設計するだけです。

+0

解決策ジョーダンありがとう。エイリアスをモジュール名で明示的に設定する方法はありますか?同様に、私はn個のモジュールを持っており、最初はすべて含まれています。エイリアスで、私が '別名:mod1_foo Module1.foo'(これは私が知っていることはできません)のような何かを使用したい場合。しかし、とにかくこれを達成するために? – user3763227

+1

はい、あなたはそうすることができますが、上記のコメントに示されているように、実際にはXY問題があるようです。すべてのメソッド名が同じである「n個のモジュール」を「インクルード」しようとすると、設計上の問題が大きくなります。 –

+0

私はn個のモジュールを持っていますが、2つだけが同じ方法を持っています。その他私はクラスの中に入れるだけです。このメソッドを廃止する計画があります。しかし、それはすぐには不可能です。そういうわけで、両方の方法を私たちが望むものと呼ぶ予定です。 – user3763227

1

あなたは、常に両方のモジュール(includeまたはextend経由で使用)ミックスインと直接呼び出すことができるようにすることができます。

module Module1 
    def foo 
    puts 'first one' 
    end 

    extend self 
end 

いつでも好きなときに、あなたがModule1.fooを呼び出すことができます。このように呼び出されたときは、モジュールのコンテキスト内にあり、それをインポートしたクラスではありません。

そのbind(self)トリックは避けるべき重大なハッカーです。ほとんどすべての場合、より一般的なRubyコードでより自然に表現できるようにコードを再構築することができます。

+1

または['module_function'](http://ruby-doc.org/core-2.4.1/Module.html#method-i-module_function)を介して。 – Stefan

+0

@Stefanそれが重要であれば、よりターゲットを絞ったアプローチのための良い解決策です。 – tadman

関連する問題