【问题标题】:How can I override a base class method using a lambda expression in java 8?如何在 java 8 中使用 lambda 表达式覆盖基类方法?
【发布时间】:2014-06-24 09:04:56
【问题描述】:

Lambda 表达式必须转换为函数式接口。据我所知,他们无法扩展一个类,但我想知道是否有办法获得类似的东西。

我有java.nio.file.SimpleFileVisitor<Path> 作为基类,我想覆盖它的一个方法,但我希望在另一个方法中这样做。我可以通过这种方式使用匿名类:

public static void printContent(Path path) throws IOException {
    FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
            System.out.println(file);
            return super.visitFile(file, attrs);
        }
    };
    Files.walkFileTree(path, visitor);
}

有没有办法在 lambda 的帮助下移除大量代码?

我认为 lambda 是 (f) -&gt; System.out.println(f);

我想过忘记 SimpleFileVisitor 并使用默认方法创建一个等效接口,但是,我如何选择要覆盖的方法?我是否需要在没有默认实现的情况下保留要覆盖的方法?在那种情况下,我需要几个接口来处理不同的情况,并使用不同的未实现的方法。

谢谢。

【问题讨论】:

  • 嗯...lambda 是函数式接口的实现,而不是抽象类。因此,您不能使用 SimpleFileVisitor 执行此操作。
  • 谢谢@kocko,但我已经在问题正文中说过了。
  • 稍微修正一下,它们没有被强制转换为函数式接口——它们有一个目标类型,而强制转换是一种为 lambda 表达式提供目标类型的方法。

标签: java lambda java-8


【解决方案1】:

使用委托。对于这个任务,你需要一个只需要实现一次的辅助类:

interface IoBiFunction<T, U, R> {
  R apply(T t, U u) throws IOException;
}
class LambdaFileVisitor<T> extends SimpleFileVisitor<T> {
    IoBiFunction<T, BasicFileAttributes, FileVisitResult> preVisitDir=super::preVisitDirectory;
    IoBiFunction<T, BasicFileAttributes, FileVisitResult> visitFile=super::visitFile;
    IoBiFunction<T, IOException, FileVisitResult> visitFailed=super::visitFileFailed;
    IoBiFunction<T, IOException, FileVisitResult> postVisitDir=super::postVisitDirectory;

    public LambdaFileVisitor<T> onVisitFile(IoBiFunction<T, BasicFileAttributes, FileVisitResult> f) {
        this.visitFile = Objects.requireNonNull(f);
        return this;
    }
    public LambdaFileVisitor<T> onVisitFailed(IoBiFunction<T, IOException, FileVisitResult> f) {
        this.visitFailed = Objects.requireNonNull(f);
        return this;
    }
    public LambdaFileVisitor<T> onPreVisitDir(IoBiFunction<T, BasicFileAttributes, FileVisitResult> f) {
        this.preVisitDir = Objects.requireNonNull(f);
        return this;
    }
    public LambdaFileVisitor<T> onPostVisitDir(IoBiFunction<T, IOException, FileVisitResult> f) {
        this.postVisitDir = Objects.requireNonNull(f);
        return this;
    }
    @Override
    public FileVisitResult visitFile(T file, BasicFileAttributes attrs) throws IOException {
        return visitFile.apply(file, attrs);
    }
    @Override
    public FileVisitResult visitFileFailed(T file, IOException exc) throws IOException {
        return visitFailed.apply(file, exc);
    }
    @Override
    public FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) throws IOException {
        return preVisitDir.apply(dir, attrs);
    }
    @Override
    public FileVisitResult postVisitDirectory(T dir, IOException exc) throws IOException {
        return postVisitDir.apply(dir, exc);
    }
}

一旦你有了你的帮助类,你就可以将它与 lambda 表达式一起使用,例如

FileVisitor<Path> fv=new LambdaFileVisitor<Path>()
  .onVisitFile((f,a)->{System.out.println(f); return CONTINUE; })
  .onVisitFailed((f,e)->{ throw e; });

FileVisitor<Path> fv2=new LambdaFileVisitor<Path>()
  .onPreVisitDir((f,a)->{System.out.println("ENTER "+f); return CONTINUE; })
  .onPostVisitDir((f,e)->{
      System.out.println("LEAVE "+f);
      if(e!=null) throw e; else return CONTINUE;
  });

【讨论】:

  • 好主意。我希望这种帮助类是 JRE 的一部分。
  • 原则上,甚至可以将这些on… 方法添加到SimpleFileVisitor 类本身,而不会破坏与在没有lambda 的情况下使用它的代码的兼容性。但是 JRE 中有很多类; JRE 开发人员根本没有足够的时间来考虑每个现有类的有用演变……
  • @Holger 你是对的,为 JRE 中的每个类添加钩子是一项乏味的练习。考虑到这一点,如果语言直接支持 lamda 覆盖会更好。也许这对 Java X 来说是一个很好的功能请求(如果还没有请求的话)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-14
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
相关资源
最近更新 更多