отличный общий свободный строитель - PullRequest
2 голосов
/ 23 марта 2012

Я хотел бы создать простую обертку, которая позволяла бы вызывать методы объектов как свободный интерфейс.Я думал о переписывании методов класса при создании, но, похоже, это не работает.Возможно ли это каким-то образом с помощью мета-программирования?Я хотел бы иметь возможность выполнить следующий фрагмент кода:

def wrappedPerson = new FluentWrapper(new Person())
wrappedPerson.setAge().setName()

Я использую Groovy 1.6.7 для этого.

Ответы [ 2 ]

2 голосов
/ 23 марта 2012

Это все Groovy, и я использую 1.8.6 (последняя версия), но учитывая этот класс Person:

class Person {
  int age
  String name

  public void setAge( int age ) { this.age = age }
  public void setName( String name ) { this.name = name }
  public String toString() { "$name $age" }
}

И этот класс FluentWrapper:

class FluentWrapper {

  def delegate

  FluentWrapper(wrapped) {
    delegate = wrapped
  }

  def methodMissing(String name, args) {
    def method = delegate.getClass().declaredMethods.find { it.name == name }
    if(method) {
      method.invoke( delegate, args )
      return this
    }
    else throw new MissingMethodException(name, delegate, args)
  }
}

Затем вы должны уметь:

def wrappedPerson = new FluentWrapper(new Person())

Person person = wrappedPerson.setAge( 85 ).setName( 'tim' ).delegate

И person должны быть указаны возраст и имя

0 голосов
/ 24 марта 2012

Я нахожу @tim_yates ' answer приятным, но вы не можете получить доступ к delegate возвращаемым методам значениям (что обычно нравится делать даже для Строителей в случае build():)

Более того, если бы это было предназначено не для Builder, а для объекта с цепочечным интерфейсом (например, для объектов с jQuery-оболочкой в ​​JS), это было бы серьезной проблемой.поместил бы обертку так:

class FluentWrapper {

  def delegate

  FluentWrapper(wrapped) {
    delegate = wrapped
  }

  def methodMissing(String name, args) {
    def method = delegate.getClass().declaredMethods.find { it.name == name }
    if(method) {
      def result = method.invoke(delegate, args)
      return result != null ? result : this
    }
    else throw new MissingMethodException(name, delegate, args)
  }
}

Обратите внимание, что оператор elvis не подходит, поскольку ложное значение никогда не будет возвращено.

Конечно, вызывающий должен знать, является лиМетод является цепным или нет, но это может быть преодолено с помощью аннотаций метода, если это необходимо.

...