我試圖避免在課堂可變實例變量,但我無法弄清楚如何在下列情況下,同時試圖在我的播放應用程序中創建一個用戶:斯卡拉:避免可變實例變量
用戶信息例如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'就可以做到這一點。它只能分配一次。 –