Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala中扩展未来[T]特性有困难_Scala_Playframework 2.0 - Fatal编程技术网

在Scala中扩展未来[T]特性有困难

在Scala中扩展未来[T]特性有困难,scala,playframework-2.0,Scala,Playframework 2.0,请原谅我对Scala不太了解。我只是一个Java开发人员,希望在Play框架中实现一些功能。我甚至试图用Java代码实现一个trait,但我得到了更模糊的错误。我有以下Scala代码: package models import scala.concurrent.Future class SettableFuture[T](name: String) extends Future[T] { var assignedValue: T def set(newValue: T)

请原谅我对Scala不太了解。我只是一个Java开发人员,希望在Play框架中实现一些功能。我甚至试图用Java代码实现一个trait,但我得到了更模糊的错误。我有以下Scala代码:

package models

import scala.concurrent.Future

class SettableFuture[T](name: String) extends Future[T] {
    var assignedValue: T

    def set(newValue: T) =
        assignedValue = newValue

    //override abstract methods in Future[T]
    def ready(atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait): models.SettableFuture[T] =
        this

    def result(atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait): T =
        assignedValue

    def isCompleted: Boolean =
        false

    def onComplete[U](func: scala.util.Try[T] => U)(implicit executor: scala.concurrent.ExecutionContext): Unit =
        null

    def value: Option[scala.util.Try[T]] =
        null
}
这是我的错误:

overriding method ready in trait Awaitable of type (atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait)SettableFuture.this.type; method ready has incompatible type
暂时忽略这些方法的返回值,它们毫无意义,因为我只是试图修复所有编译错误

在扩展trait时,我只是从编译时异常复制了方法存根,而没有覆盖它的抽象方法,并将它们粘贴到源文件中。我不明白为什么我还是会出错。我查看了waitiable中ready()的签名,看起来返回类型实际上应该是类

编辑:我之所以要实现这一点,是因为在Promise/Future Scala API中,我只能找到让我异步执行长时间运行的阻塞任务的东西。我所追求的是让请求的执行暂停,直到感兴趣的东西在SettableFuture实例中设置了一个值,这就完成了发送响应的承诺。这样,它有点像一个延续。总之,以下是我最终得到的工作代码:

package models

import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger

import scala.concurrent.CanAwait
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.duration.Duration
import scala.util.Try

class SettableFuture[T]() extends Future[T] {
    private final val ValueNotSet = 0
    private final val ValueBeingSet = 1
    private final val ValueSet = 2

    private val valueStatus: AtomicInteger = new AtomicInteger(ValueNotSet)
    private val onCompleteWaitHandle: CountDownLatch = new CountDownLatch(1)
    private var onComplete: Try[T] => _ = _
    private var assignedValue: T = _

    /** Set a value and complete this Future.
      *
      * Returns false if the value has already been set by a past call to this method.
      * Otherwise, marks this Future as complete, executes the function passed to
      * onComplete, and finally returns true.
      */
    def set(newValue: T): Boolean = {
        //set value and trigger onComplete only once
        if (valueStatus.compareAndSet(ValueNotSet, ValueBeingSet)) {
            assignedValue = newValue
            valueStatus.set(ValueSet)
            onCompleteWaitHandle.countDown()
            if (onComplete != null)
                onComplete(Try(assignedValue))
            true
        }
        false
    }

    //override abstract methods in the Future[T] trait
    def ready(atMost: Duration)(implicit permit: CanAwait): this.type = {
        onCompleteWaitHandle.await(atMost.length, atMost.unit)
        this
    }

    def result(atMost: Duration)(implicit permit: CanAwait): T = {
        ready(atMost)
        assignedValue
    }

    def isCompleted: Boolean = (valueStatus.get() == ValueSet)

    def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit =
        onComplete = func

    def value: Option[Try[T]] = {
        if (!isCompleted)
            None
        Some(Try(assignedValue))
    }
}

就您得到的特定错误而言,您正在重写的
ready
方法的返回类型为
Awaitable。this.type
-即
Awaitable的此实例的特定类型(超级类型的
Future
,因此在
Future
中,此方法被视为具有返回类型
Future.this.type
)。对于
SettableFuture
类,这意味着
ready
方法的返回类型必须是
models.SettableFuture.this.type

您可能会遇到的其他小问题:
onComplete
方法的实现应该是
{}
,而不是
null
,因为后者是类型
null的返回。类型
,而不是
Unit
,var
赋值
需要在非抽象类中初始化,这可以通过将
=\ucode>添加到定义变量的行中来完成(尽管您确实希望使其至少受到
保护
,并提供一个访问器,该访问器将检查它是否已设置-可能通过将变量更改为
选项[T]
初始化为
None
,或者维护可在访问器中检查的
布尔
标志,并通过
set
方法将其设置为
true


然而,就您试图实现的目标而言,您可能只想查看
scala.concurrent.Promise
,它表示“对未来结果的承诺”。它有一个方法
future
,返回一个
future
,以及各种
complete
completeWith
,以及类似的方法,可用于设置
承诺的值,这反过来将导致相关的
future
变得就绪/完成。

可设置的future
类unne成功地混合了
未来
承诺
特征旨在分离的两个关注点:

  • 异步提供值(
    Promise
    ),以及
  • 等待并对该条款作出反应(
    未来
与其将
未来的
视为异步、长时间运行的阻塞计算,不如将其简单地视为未来某个时间可能提供的值。您可以通过多种方式对该值的提供作出反应,包括注册回调或将其映射到其他值。例如,在Play one wi中ll通常会使用如下模式(在Scala中)暂停对请求的处理:

gimmeAFuture方法返回一个
Future
,但是请求处理代码不关心如何计算该值

  • 使用
    Future立即计算。成功
  • Future异步计算。应用
    ,或
  • 通过完成
    承诺
作为后者的示例,
gimmeAFuture
方法可以实现如下:

def gimmeAFuture: Future[JsValue] = {
  val p = Promise.apply[JsValue]()
  // asynchronously complete the promise 30 seconds from now
  scheduler.scheduleOnce(30.seconds)(p.complete(Success(someJsObject)))
  // return the future immediately
  p.future
}

当然,您可以随心所欲地实现该方法。关键是某些东西需要保留该
Promise
对象,并使用一个值来完成它,以便恢复对请求的处理。请求处理程序本身不会获得对
Promise
对象的引用,因为它只关心该对象的值将被计算(即,承诺的未来)。

在找到这个问题后,我重新审视了这个问题,并意识到为什么会有这么多困惑

我计划使用SettableFuture类,因为我在Play Java API中找不到任何类似的类。我想要与.NET中的TaskCompletionSource等效的东西,Aaron的回答清楚地表明Scala正好满足了我的需要。不幸的是,我在Play的Java API中找不到等效的东西


这个链接清楚地解释了为什么我在本应如此简单的事情上遇到如此多的困难。谢谢大家回答我的问题!

谢谢你们的帮助。我现在已经完全可以使用Scala代码了。至于承诺和未来的部分,我不确定这是否正是我想要实现的。我感觉像大多数API deals处理长时间运行的阻塞任务。我要做的是让请求的执行暂停,直到感兴趣的东西在SettableFuture实例中设置了一个值,这就完成了发送响应的承诺。这样,它有点像一个延续。您知道Scala库中存在的任何可以像这样的东西?@KevinJin这正是
承诺的目的。设置值的代码包含对
def gimmeAFuture: Future[JsValue] = {
  val p = Promise.apply[JsValue]()
  // asynchronously complete the promise 30 seconds from now
  scheduler.scheduleOnce(30.seconds)(p.complete(Success(someJsObject)))
  // return the future immediately
  p.future
}