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

Groovy有选择地从多个类混合方法,groovy,multiple-inheritance,mixins,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 FileAlterationL

我正在编写一个基于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()
    方法
  • deleteoDeleteListener
    包含用于删除
    destination()
    方法返回的CSS文件的
    onFileDelete()
    方法
有没有一种“Groovy方式”可以选择性地将这两个类中的方法混合或继承到一个新类中?


还是我只需要咬紧牙关,为
CompileLessOnWriteListener
DeleteCssOnDeleteLessListener
创建一个通用的超类?

更新

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

  • 继承两种方法
  • “继承”构造函数
  • 它需要是一个接口的实例
我认为重元编程在这方面有帮助。我们可以将两个对象声明为
DeleteCssOnDeleteLessListener
将方法委托给,这些对象将从中访问属性

对于接口,我认为最好使用
作为接口
操作符

动态“继承”构造函数可能会变得棘手。因为它只有两个属性,所以我声明了它们。如果您喜欢干燥代码,可以将
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"

更新

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

  • 继承两种方法
  • “继承”构造函数
  • 它需要是一个接口的实例
我认为重元编程在这方面有帮助。我们可以将两个对象声明为
DeleteCssOnDeleteLessListener
将方法委托给,这些对象将从中访问属性

对于接口,我认为最好使用
作为接口
操作符

动态“继承”构造函数可能会变得棘手。因为它只有两个属性,所以我声明了它们。如果您喜欢干燥代码,可以将
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"
在我看来,它不是很“Groovy”,也不是很高效,但至少这种方法解决了我的问题,而不必创建一个通用的超类:

class DeleteCssOnDeleteLessListener extends DeleteOnDeleteListener {
    @Override
    File destination(File f) {
        new CompileLessOnWriteListener(destDir: this.destDir, srcDir: this.srcDir).destination(f)
    }
}
在我看来,它不是很“Groovy”,也不是很高效,但至少这种方法解决了我的问题,而不必创建一个通用的超类:

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

不完全是。首先,我无法在初始化时设置srcDir和destDir属性,例如
(新的DeleteCssOnDeleteLessWriter(srcDir:s,destDir:d)
。其次,我需要让DeleteCssOnDeleteLessWriter成为FileAlterationListener的一个实例。遗憾的是,我不能通过实现接口来做到这一点,尽管我可以动态地做到:
observer.addListener(delCssListener作为FileAlterationListener)
。最后,mixin包括
onFileCreate
onFileChange
方法。我所需要的只是
onFileDelete
,因此是“选择性地”问题的一部分。关于
@Delegate
?它会自动继承接口。我是否可以选择性地
@Delegate
?我错过了您编辑答案的通知。让我试试,然后再给您回复。它看起来很有希望。哇,我没有记住这个:-)不太清楚。首先,我无法在初始化时设置srcDir和destDir属性,例如
(新的DeleteCssOnDeleteLessWriter(srcDir:s,destDir:d)
。其次,我需要让DeleteCssOnDeleteLessWriter成为FileAlterationListener的一个实例。遗憾的是,我不能通过实现接口来做到这一点,尽管我可以动态地做到:
observer.addListener(delCssListener作为FileAlterationListener)
。最后,mixin包括
onFileCreate
onFileChange
方法。我所需要的只是
onFileDelete
,因此是“选择性地”问题的一部分。关于
@Delegate
?它会自动继承接口。我可以有选择地
@Delegate
?我错过了你编辑答案的通知。让我试试,然后再给你回复。它看起来很有希望。哇,我不记得这个了:-)