【问题标题】:Scala wrapper API for java API用于 java API 的 Scala 包装器 API
【发布时间】:2016-05-20 06:23:45
【问题描述】:

我是 Scala 新手,我需要为我的 Java API 提供一个 scala 包装器

我有三个 Java 接口

public interface Client<T> {

   <T> Future<T> execute(App<T> app);

}

public interface App<T> extends Serializable{

  T process(AppContext context) throws Exception;

}

public interface AppContext {

  File getDirectory();

  void deleteDirectory();

  File createDirectory(String path);

}

以下是创建 App 的 Java 代码

public class RandomApp extends App<String> {

  @Override
  public String process(AppContext context) {

      // Inorder to access the methods in AppContext I need to access  
      // it by the following way

      appContext.createDirectory("some path");
      return "random";
  }
 }

我想要一个用于客户端接口的 Scala 包装器,它反过来调用 Java API。但我对新的 Scala API 做了一些修改

object ScalaConverter {

  implicit class ScalaWrapper(client: Client) {

  def scalaClient = new ScalaClient(client)

  }
}

class ScalaClient(client: Client) {

  def execute[T](appContext: AppContext => T): Future[T] = {

      // I am passing appContext as closure instead of passing in
      // App because I want to take the advantage of Closures in Scala

      // I basically want to create an App with this appContext and
      // pass it to the execute method

      // For example - but this is not working

      var app = // Need to create this app with appContext

      Future {
        client.execute(app)
      }
  }

}

【问题讨论】:

  • 对不起,如果我的帖子不清楚。我想从 appcontext 创建一个 app 对象,因为 Java API 是 execute(app)

标签: java scala closures scala-collections


【解决方案1】:

如果我没记错的话,您只是希望能够从一个以 AppContext 作为参数并返回任意对象(比如说 T)的函数创建 App 对象。

因为尝试镜像整个 java API 并不是很有趣,所以直接使用它,但添加一些扩展。为此,您应该使用隐式。

为此,我看到了两种可能性:要么在Client 接口上添加一个隐式类以向其中添加一些函数,要么添加从(AppContext =&gt; T)App 对象的隐式转换。

让我们开始第一个解决方案,您必须将隐式类嵌入到一个对象中(如果您需要自动导入,这可以是一个包对象)。

object ScalaConverter {
  class ScalaApp[T](val block: AppContext => T) extends App[T] {
    def process(context: AppContext): T = block(context)
  }

  implicit class ScalaClient(client: Client) extends AnyVal{
    def execute[T](block: AppContext => T): Future[T] = {
      client.execute(new ScalaApp(block))
    }
  }
}

然后,您只需使用现有的 java Client 对象:

import ScalaConverter._
myJavaClient.execute { context => 
   ???
}

你应该明白原理,我可能犯了一个错误(没有尝试编译这个)

【讨论】:

  • 另外,您能否解释一下def process(context: AppContext): T = block(context) 的工作原理。我理解正在使用的闭包的概念。但是我仍然无法在这段代码中得到它
  • 我收到一个运行时错误 - 在 (AppContext)T 类型的 trait App 中覆盖方法 process - 方法调用的类型不兼容..
  • 其实。那是因为我们将隐式类作为值类。 Tat 解决了这个问题。但是,如果有人可以发布为什么隐式类不能成为此代码中的值类,那就太好了
  • 方法def process(context: AppContext): T = block(context)有效,因为block参数被定义为一个以AppContext为参数并返回T的函数。所以,当调用process方法时,我们调用函数由块定义,将接收到的上下文作为参数提供给它,并返回它的值。
  • 我编辑了我的答案;值类可能不包含内部类。因此,我刚刚提取了匿名 App 类。有关详细信息,请参阅docs.scala-lang.org/overviews/core/…
猜你喜欢
  • 2016-09-25
  • 2012-08-02
  • 2016-05-03
  • 2010-12-28
  • 2023-03-20
  • 1970-01-01
  • 2021-02-18
  • 2021-02-28
  • 1970-01-01
相关资源
最近更新 更多