【发布时间】:2015-12-09 17:40:16
【问题描述】:
在我的应用程序中有资源,其中许多以相同的方式加载,所以我想抽象方法。
我创建了一个名为Resources的特征
现在这个特征需要完成三个任务。
- 它为任意数量的
Resources 实现了一个缓存。 - 它为所有可以加载该类型资源的加载器实现了一个映射。 (例如,对于可能包含“PNGLoader”、“JPGLoader”甚至“GIFLoader”的资源图像)
- 实现用于在给定路径检索资源的通用/默认方法
看起来像这样:
trait Resources
{
private val loaders: mutable.HashMap[String, ResourceLoader] = new mutable.HashMap[String, ResourceLoader]
private val cache: mutable.HashMap[String, Resource] = new mutable.HashMap[String, Resource]
def get(path: String): Resource =
{
// Check cache... if fail, see if there is a loader registered
}
private def load(path: String): Resource =
{
// Check if there is a loader for the file, if so loader.load(path)
}
def registerLoader(...)
}
trait ResourceLoader
{
def load(path: String): Resource
}
trait Resource
现在想象一下:
class Image extends Resource
object Images extends Resources
object PNGLoader extends ResourceLoader
{
Textures.register("png", this)
override def load(path: String): Image =
{
// Do some magic
}
}
现在,有一个问题。这种方法可行(我已经尝试过),但问题是:
val img: Image = Images.get("images/test.png")
会导致类型不匹配,因为 Image != Resource。
所以我需要这样做
val img: Resource = Images.get("images/test.png")
或手动投射。两者都不是一个真正的选择。
现在,我尝试使用这样的东西:
trait Resources[ResourceType <: Resources[ResourceType]]
{
private val cache: mutable.HashMap[String, ResourceType] = new mutable.HashMap[String, ResourceType]
def get(path: String): ResourceType = {...}
}
trait ResourceLoader[ResourceType <: ResourceLoader[ResourceType]]
{
def load(path: String): ResourceType
}
但这当然行不通,因为虽然类型命名完全一样,但没有共享信息,所以“ResourceType (of ResourceLoader) != ResourceType (of Resources)”所以loader.load(path) 不能工作。
总结:我想返回一个 ConcreteType(对于一个 ImageLoader 应该是一个 Image,对于一个 VideoLoader 这应该是一个 Video),但是有不同的类负责缓存,比如“图片”和“视频”,所以我可以这样做:
val video: Video = Videos.get(...) 和 val image: Image = Images.get(...)
所以所有东西都应该有不同的缓存(这样我就可以刷新所有视频或所有图像等)
另外,我刚刚看到,我可能需要将 private 更改为 protected g
【问题讨论】:
标签: scala generics inheritance polymorphism return-type