从多个类中有选择地混合方法的Groovy方法

时间:2013-05-10 18:59:26

标签: groovy multiple-inheritance mixins

我正在编写一个基于commons-io的Groovy脚本,它监视一些源目录并将其文件与某个目标目录同步。

@Grab(group='commons-io', module='commons-io', version='2.4')
import org.apache.commons.io.monitor.*
import org.apache.commons.io.FileUtils
class BaseSynchronizedFileListener extends FileAlterationListenerAdaptor {
    def srcDir
    def destDir   
    /* Given a source file, returns the destination file */
    File destination(File file) {
        new File(destDir, file.getAbsolutePath() - srcDir.getAbsolutePath())
    }
}
class CopyOnWriteListener extends BaseSynchronizedFileListener {
    @Override 
    void onFileChange(File file) {
        FileUtils.copyFile(file, destination(file))
    }
    @Override
    void onFileCreate(File file) { 
        FileUtils.copyFile(file, destination(file))
    } 
}
class DeleteOnDeleteListener extends BaseSynchronizedFileListener {
    @Override
    void onFileDelete(File file) {
        FileUtils.deleteQuietly(destination(file))
    }
}

除了直接文件副本,我还想支持Less-> CSS编译,其中源目录中的.less文件与目标目录中的.css文件同步。

@Grab(group='org.lesscss', module='lesscss', version='1.3.3')
import org.lesscss.LessCompiler
class CompileLessOnWriteListener extends BaseSynchronizedFileListener {
    def compiler = new LessCompiler()
    @Override
    File destination(File file) {
        File dest = super.destination(file)
        new File(dest.parentFile, dest.name - '.less' + '.css')
    }
    void compile(File less) {
        compiler.compile(less, destination(less))
    }
    @Override
    void onFileChange(File less) {
        compile(less)
    }
    @Override
    void onFileCreate(File less) { 
        compile(less)
    } 
}

我遇到的问题是当我尝试创建类DeleteCssOnDeleteLessListener来处理删除.less文件时的情况(反过来删除相应的.css文件) - 我需要做的代码存在于两个不同的继承树中。

  • CompileLessOnWriteListener包含destination()方法
  • DeleteOnDeleteListener包含onFileDelete()方法,用于删除destination()方法返回的CSS文件

是否有“Groovy方式”选择性地将这两个类中的方法混合或继承到新类中?

或者我只需要咬紧牙关并为CompileLessOnWriteListenerDeleteCssOnDeleteLessListener创建一个共同的超类?

2 个答案:

答案 0 :(得分:1)

<强>更新

更改了实施。让我们看看我是否有这个想法。你需要:

  • 继承两种方法
  • “继承”构造函数
  • 它必须是接口的实例

我认为重要的元编程有助于此。我们可以向DeleteCssOnDeleteLessListener委托方法声明两个对象,这些对象将从中访问属性。

对于界面,我认为您最好使用as Interface运算符。

动态“继承”构造函数可能会变得棘手。由于它只有两个属性,我已经声明了它们。如果您希望干燥代码,可以将getProperty / setProperty委托给其他两个对象之一:

class DeleteCssOnDeleteLessListener {
  def destDir, srcDir
  def onLessDelete(file) {
    onFileDelete destination( file )
  }
}

class CompileLessOnWriteListener {
  def destination(file) {
    "destination $file from $srcDir"
  }
}

class DeleteOnDeleteListener {
  def onFileDelete(file) {
    "onFileDelete $file and $destDir"
  }
}

def delete = new DeleteCssOnDeleteLessListener(destDir: "dest/dir", srcDir: "src/dir")
def compileLess = new CompileLessOnWriteListener()
def deleteOnDelete = new DeleteOnDeleteListener()

delete.metaClass {
  destination = compileLess.&destination
  onFileDelete = deleteOnDelete.&onFileDelete
}

compileLess.metaClass.getProperty = { property -> delete.getProperty property }
deleteOnDelete.metaClass.getProperty = { property -> delete.getProperty property }

assert delete.onLessDelete("style.less") == "onFileDelete destination style.less from src/dir and dest/dir"

答案 1 :(得分:0)

在我看来,它不是非常“Groovy”,也不是非常高效的外观,但至少这种方法可以解决我的问题,而无需创建一个共同的超类:

class DeleteCssOnDeleteLessListener extends DeleteOnDeleteListener {
    @Override
    File destination(File f) {
        new CompileLessOnWriteListener(destDir: this.destDir, srcDir: this.srcDir).destination(f)
    }
}