代码之家  ›  专栏  ›  技术社区  ›  Aaron Rustad

如何在不使用继承的情况下向控制器添加常见操作?

  •  3
  • Aaron Rustad  · 技术社区  · 15 年前

    我需要在不使用继承的情况下向我的一些控制器添加公共操作。我们所有的控制器都扩展了一个抽象控制器,我想要包含的功能在抽象控制器中没有意义。

    我最初的想法是使用一个mixin,但似乎操作,因为它们是闭包,不会“混合”到包含mixin的控制器中,只有方法是。

    有人能给我一个类似“混合”功能的方法来向控制器添加操作吗?

    谢谢!

    4 回复  |  直到 14 年前
        1
  •  6
  •   Jean Barmash    15 年前

    方法是迭代控制器,并使用元编程向其添加方法。

    例如,检查perf4j插件(文件perf4jgrailsplugin.groovy)。

    在里面,你会看到:

    application.controllerClasses.each() {
                addPerf4jMethods(it.clazz, log)
            } 
    
    def addPerf4jMethods(artefactClass, log) {
            log.info "Adding Per4j methods: ${artefactClass}..."
    
    
            artefactClass.metaClass.withStopwatch << { Closure callable ->
                withStopwatch("", null, callable)
            }
    
            artefactClass.metaClass.withStopwatch << { String tag, Closure callable ->
                withStopwatch(tag, null, callable)
            } 
    }
    

    在上面的代码中,您将遍历所有控制器,并使用秒表添加方法,因此它们现在可以在任何地方使用。如果您只需要在一些控制器中执行此操作,显然可以进行额外的检查。

    您可以将这段代码放入bootstrap.groovy中,这样它就可以在应用程序每次启动时运行。

        2
  •  7
  •   Michael Borgwardt    15 年前

    我们所有的控制器都扩展了一个抽象的 控制器和功能I 要包含在中没有意义 抽象控制器。

    那么为什么不让第二个抽象控制器扩展基本控制器,而只由那些需要这个功能的控制器扩展呢?

    对我来说,这听起来是最简单、最干净的解决方案——当然比使用元编程更好。”“喜欢组合而不是继承”并不意味着继承从根本上来说是一件肮脏的事情,应该不惜一切代价避免。

        3
  •  2
  •   Ted Naleid    15 年前

    在这种情况下,我经常使用的第三个选项是静态导入。这实际上是许多人都不知道的Java(不是Groovy)的一部分。

    因此,如果您有这样一个类,并且希望共享静态方法:

    class Foo {
        static baz = { -> 
            return "baz!"
        }
    }   
    

    并在要使该方法可用的类中使用“import static”:

    import static Foo.baz
    
    class Bar {
        static void main(String[] args) {
            assert "baz!" == baz.call()
        }
    }
    

    不需要超类或混合魔法,让编译器为您完成工作。

        4
  •  1
  •   fabien7474 Jan Tchärmän    14 年前

    根据新的颗粒 dynamic-controller plugin ,它:

    允许您动态创建控制器并向现有控制器添加操作

    使用MIXIN。

    它似乎符合你的要求。