2

私は2つのクラスを持っています。実行時に、あるオブジェクトのメソッドを別のオブジェクトに「複製」したいと考えています。これは可能ですか?左シフトを使用して失敗した試みを以下に示します。

(注:同じ結果で currMethod.clone() も試しました。)

class SandboxMetaMethod2 {
    String speak(){
        println 'bow wow'
    }
}

class SandboxMetaMethod1{

  void leftShift(Object sandbox2){
      sandbox2.metaClass.getMethods().each{currMethod->
          if(currMethod.name.contains("speak")){
              this.speak()
              this.metaClass."$currMethod.name" = currMethod
              this.speak()
          }
      }
  }

  String speak(){
    println 'woof'
  }
}

class SandboxMetaMethodSpec extends Specification {
    def "try this"(){
        when:
        def sandbox1 = new SandboxMetaMethod1()
        def sandbox2 = new SandboxMetaMethod2()
        sandbox1 << sandbox2


        then:
        true
    }

}


//Output
woof
speak
woof

リクエストごとに、目標/ユースケースに関する背景を追加しています:

これは、標準的な機能タイプのユース ケースに非常によく似ています。要約すると、すべてのクライアント環境 (50 ~ 100) に適用されるクラスに多くのメソッドがあります。これらを適用して、特定のデフォルトの順序でデータを処理します。これらのメソッドのそれぞれは、クライアント固有のメソッド (同じメソッド名で存在する場合) によってオーバーライドされる可能性があり、上記のアプローチを使用してメソッドセットを「調整」するというアイデアがありました。クライアント環境名に基づいて、メソッドを動的にオーバーライドする方法が必要です。

注: メタクラスでメソッドをオーバーライドすることは非常に標準的です (または、それが驚くべき機能が存在する理由です)。そして、メソッドが String currMethod = "{x-> x+1}" のようなテキストとして存在する場合に機能する場合は、this.metaClass."$currMethodName" = currMethod と言うだけです。この場合の私の課題は、メソッドがコンパイルされ、どこかでテキストとして定義されるのではなく、別のクラスに存在することです。

すべてのカスタム メソッドをビルド時にクライアント固有のクラスにコンパイルする目的は、計算ごとに実行時にこれらの動的メソッドをコンパイルするコストを回避することでした。ビルド時間。この方法では、クライアント固有のコードのみをそれぞれのクライアントに展開することもできます。マスター クラスで他のすべてのクライアントの計算は必要ありません。

それが理にかなっていることを願っています。

Jeremie B の提案に対する新しいアプローチ:

実行時に名前で実装する特性を選択する必要があるため、次のように機能します。

String clientName = "client1"
String clientSpeakTrait = "${clientName}Speak"

trait globalSpeak {
    String speak() {
        println 'bow wow'
    }
}

trait client1Speak {
    String speak() {
        println 'woof'
    }
}

def mySpeaker = new Object().withTraits globalSpeak, clientSpeakTrait
4

1 に答える 1

1

Traits を使用した基本的な例:

trait Speak {
    String speak() {
        println 'bow wow'
    }
}

class MyClass {

}

def instance = new MyClass()
def extended = instance.withTraits Speak

extended.speak()

実行時に使用する特性を選択できます。

def clientTrait = Speak
def sb = new Object().withTraits(clientTrait)

sb.speak()

ClassLoader を使用してトレイトを動的にロードします。

def clientTrait = this.class.classLoader.loadClass "my.package.${client}Speak"
def sb = new Object().withTraits(clientTrait)
于 2016-02-27T16:07:04.023 に答える