2013-04-01 35 views
3

我正在构建具有惊人数量抽象的ubercool应用程序。 现在我要设计过度设计的EntityGetService。选项和未来

我想的第一件事是很多抽象类,让说,这样的事情:这里

trait EntityGetService[ID, ENTITY, CONTAINER] { 
    def get(id: ID): CONTAINER 
} 

容器的东西,包含(或不包含)键入所需的实体。与选项[ENTITY]非常相似。但是我想要的第二件事,那就是CONTAINER也可以成为未来[ENTITY]。

所以我真的想写特点是这样的:

trait EntityGetService[ID, ENTITY, CONTAINER <: Wrapper[ENTITY]] { 
    def get(id: ID): CONTAINER 
} 

,在这种方式指定它:

trait EntitySyncGetService[Long, Entity, Option[Entity]] { 
    def get(id: Long): Option[Entity] 
} 

trait EntityAsyncGetService[Long, Entity, Future[Entity]] { 
    def get(id: Long): Future[Entity] 
} 

有没有办法做到这一点,而无需重新延长或混合的东西期权和未来?

它看起来像期权和未来有一点共同的(他们两个集装箱)。这与单子有关吗?

还是这只是一个我的失眠的产品?

回答

3

不评论这一切的合理性,可以使用更高阶的类型:

trait WrappedGetService[ID, ENTITY, WRAPPER[_]] { 
    def get(id: ID) : WRAPPER[ENTITY] 
} 

,那么你可以声明WrappedGetService[Long, Entity, Option]

更新:一些参考

该功能被称为高阶类型(可能更高kinded类型太)或类型的构造函数

  • the language specification,它应该出现主要是在部分 4.4,类型参数,但不会有很多关于它,它的工作原理就像其他类型的参数。
  • 的功能在纸Generics of a higher kind纸张可能无法精确地实现为在 语言最初提出的,但它应该是非常接近的。另一方面,收藏品库又是另一种方式,您可能会在Fighting Bit Rot with Types中看到为什么。
  • 你可能会看看scalaz库(不适合心脏不好)。如果你这样做,你可能也想看看Haskell。
+0

看起来像这是我正在寻找。你能指出一些资源来阅读这个功能吗?快速的谷歌搜索没有显示任何有用的信息。 –

3

你可以通过一些我称之为“手动AOP”的东西来达到这个目的。

先用AA方法定义一些基础性状捕获包裹一个Option内的结果的概念,一个Future,或任何其他的容器中,一起进行实际的包装:

import concurrent._ 

trait AbstractService { 
    type Result[T] 
    protected def result[T](code: => T) : Result[T] 
} 

然后专门此基特质为FutureOption案件:

trait SyncService extends AbstractService { 
    type Result[T] = Option[T] 
    // Returns the original result wrapped in Some, 
    // or None if it was null or an exception occured 
    protected def result[T](code: => T) : Option[T] = { 
    try { 
     Option(code) 
    } catch{ case ex: Throwable => 
     ex.printStackTrace() 
     None 
    } 
    } 
} 

trait AsyncService extends AbstractService { 
    type Result[T] = Future[T] 
    protected val execContext: ExecutionContext 
    protected def result[T](code: => T) : Future[T] = { 
    future(code)(execContext) 
    } 
} 

现在你去好,可以这样定义你的EntityGetService特点:

trait EntityGetService[ID, ENTITY] extends AbstractService { 
    def get(id: ID): Result[ENTITY] = result { 
    ??? 
    } 

    // add all the other method implementations here, taking care to 
    // wrap the method bodies inside "result" 
} 

// Now specializing EntityGetService as a sync or async service is just a matter 
// of mixing SyncService or AsyncService: 

class EntitySyncGetService[Long, Entity] extends EntityGetService[Long, Entity] with SyncService 
class EntityAsyncGetService[Long, Entity](implicit val execContext: ExecutionContext) extends EntityGetService[Long, Entity] with AsyncService 
+0

太棒了!你把我的思想包裹在里面。 –

相关问题