【发布时间】:2013-12-08 13:02:28
【问题描述】:
我在下面的 typeclass 中遇到了一些奇怪的问题:由于某种原因,隐式对象 ContentUploader 在调用 DemoActor 的 upload 方法时无法解析。
import akka.actor.Actor
import java.io.File
import org.slf4j.LoggerFactory
class DemoActor extends Actor {
import DemoActor.UploaderImpl._
override def receive = {
case (x: DemoActor.Content) =>
DemoActor.upload(x)
}
}
object DemoActor {
val LOG = LoggerFactory.getLogger("DemoActor")
sealed trait UploadData {
val data: Array[File]
}
case class Content(data: Array[File]) extends UploadData
case class UploadResult(url: String, contentType: String, size: Long)
trait S3Uploader[T <: UploadData] {
def uploadToS3(filez: Array[File]): Iterable[UploadResult]
}
object UploaderImpl {
val LOG = LoggerFactory.getLogger("Uploader")
private def contentType(name: String): String = {
"application/octet-stream"
}
private def doUpload(filez: Array[File], bucketName: String) = {
LOG.debug("Uploading: {} to {}", filez, bucketName)
filez.flatMap {
case f =>
try {
val key = f.getName
val mime = contentType(f.getName)
Some(UploadResult("http://" + bucketName + ".s3.amazonaws.com/" + key, mime, f.length()))
} catch {
case e =>
LOG.error("Can not upload", e)
None
}
}
}
implicit object ContentUploader extends S3Uploader[Content] {
lazy val bucketName = "resources.aws.bucketname"
lazy val awsSecret = "resources.aws.secret.key"
lazy val awsAccess = "resources.aws.access.key"
override def uploadToS3(filez: Array[File]) = doUpload(filez, bucketName)
}
}
def upload[T <: UploadData](src: T)(implicit uploader: S3Uploader[T]) = uploader.uploadToS3(src.data)
}
我在这里错过了什么?
UPD
如果我将 DemoActor 的 class 定义移动到 object DemoActor 中,例如
import akka.actor.Actor
import java.io.File
import org.slf4j.LoggerFactory
object DemoActor {
val LOG = LoggerFactory.getLogger("DemoActor")
sealed trait UploadData {
val data: Array[File]
}
case class Content(data: Array[File]) extends UploadData
case class UploadResult(url: String, contentType: String, size: Long)
trait S3Uploader[UploadData] {
def uploadToS3(filez: Array[File]): Iterable[UploadResult]
}
object UploaderImpl {
val LOG = LoggerFactory.getLogger("Uploader")
private def contentType(name: String): String = {
"application/octet-stream"
}
private def doUpload(filez: Array[File], bucketName: String) = {
LOG.debug("Uploading: {} to {}", filez, bucketName)
filez.flatMap {
case f =>
try {
val key = f.getName
val mime = contentType(f.getName)
Some(UploadResult("http://" + bucketName + ".s3.amazonaws.com/" + key, mime, f.length()))
} catch {
case e =>
LOG.error("Can not upload", e)
None
}
}
}
implicit object ContentUploader extends S3Uploader[DemoActor.Content] {
lazy val bucketName = "resources.aws.bucketname"
lazy val awsSecret = "resources.aws.secret.key"
lazy val awsAccess = "resources.aws.access.key"
override def uploadToS3(filez: Array[File]) = doUpload(filez, bucketName)
}
}
def upload[T <: UploadData](src: T)(implicit uploader: S3Uploader[T]) = uploader.uploadToS3(src.data)
class DemoActor extends Actor {
import DemoActor.UploaderImpl._
override def receive = {
case (x: DemoActor.Content) =>
DemoActor.upload(x)
}
}
}
然后一切正常。命名空间是否存在一些问题?
【问题讨论】: