我试图避免在课堂可变实例变量,但我无法弄清楚如何在下列情况下,同时试图在我的播放应用程序中创建一个用户:斯卡拉:避免可变实例变量
用户信息例如membershipList可以在用户登录时更改。当这种情况发生变化时,应用程序将使用Play的Ok.feed(...)
作为服务器发送事件(SSE)通知用户。
编辑:@drstevens指出,必须将单播馈送移出,因为User
显示为Case类。编辑User
不是案例分类。在控制器
class User(id: Long, firstName: String, lastName: String,
membershipList: List[Group], @volatile private var signedIn = true) {
private var infoSentOnce = false;
private val unicastFeed: Option[Enumerator[JsValue]] = if(signedIn) Concurrent.unicast[JsValue](onStart, onComplete, onError) else None
private def onStart(channel: Channel[JsValue]) {
if(signedIn) {
if(!infoSentOnce) {
channel.push(json)
channel.end
infoSentOnce = true;
}
} else {
channel.eofAndEnd
}
}
private def onComplete = ....
private def onError(message: String, iteratee: Iteratee[JsValue]) = .....
def json = {
.....
}
def signedOut = signedIn = false
def feed = unicastFeed
}
行动将是:
class MyController extends Controller with MyAuth {
def userFeed = Authenticated { request =>
request.user.feed.fold(Ok(request.user.json)) { feed =>
Ok.feed(feed
>& Concurrent.buffer(10)
>& new EventSource()).as("text/event-stream"))
}
}
}
signedIn
& infoSentOnce
是两个可变的变量,我想改变它是不可变的。可变的infoSentOnce
也可能与我没有正确理解Play的枚举器有关。每当用户信息发生变化时,我都会创建一个新的User对象,但是我会从同一用户的前一个实例复制Unicast枚举器。在创建新用户实例时,Json将被推入用户的单播频道。
也许有infoSentOnce
因为var在这里没问题,因为它不能被任何外部交互修改?
你有没有一个完整的例子,你正在尝试做什么?如何使用枚举器?何时使用?我仍然会尝试将'Enumerator'部分与'User'分开。 – drstevens
@drstevens更新了问题的更多细节。 – Prasanna
如果你想做一次不可变的初始化,那么'lazy val'就可以做到这一点。它只能分配一次。 –