2013-06-12 82 views
1

我想知道是否有人有任何創建類型參數化類型層次結構的經驗?我相當肯定這是由於scala僞靜態包裝對象的結合而導致的。類型參數化類型層次結構

具體使用情況下,我心目中是一個參數化類型的id在應用程序框架,所以你可以使用的int/long/java.util.UUID/BSONId /不管你的選擇。考慮作爲一個粗略的例子:

package object myprj { 
    object foolib extends foolib.generic.FooTaxonomy[java.util.UUID] 

    // Whee! 
    val someEntity = new myprj.foolib.Entity(java.util.UUID.randomUUID()) 
} 

是否有任何理由,這是一個引人注目的壞主意:

package foolib.generic 

trait GenEntity[I] { def id: I } 

trait GenRepository[I] { def getById(id: I): GenEntity[I] } 

trait FooTaxonomy[I] { 
    type Entity = GenEntity[I] 
    type Repository = GenRepository[I] 

    object subpackage extends generic.subpackage.SubpackageTaxonomy[I] 
} 

你會再與類似配置使用層次的項目呢?任何陷阱/我應該知道的?

+1

可能是我,但我不明白你想達到的目標。 – Jatin

回答

1

此方法可行,但類型參數數量增加時可能會遇到問題。也許解決方法是使用抽象類型成員而不是類型參數。

另一種方法是使用蛋糕模式,我認爲你的情況提供了一個更好的解決方案。你的代碼的確切邏輯躲開了一點,所以這個重寫可能不完全代表你的意圖:

package foolib.generic 


//defines common types used by all modules 
trait CoreModule { 

    type Id // abstract type, not commited to any particular implementation 

} 

//module defining the EntityModule trait 
trait EntityModule { this: CoreModule => //specifying core module as a dependency 

    trait GenEntity { 
     def id: Id 
    } 

    def mkEntity(id: Id): Entity //abstract way of creating an entity 

} 

//defines the GenRepository trait 
trait RepositoryModule { this: EntityModule with CoreModule => //multiple dependencies 

    trait GenRepository { 
     def getById(id: Id): GenEntity 
    } 

    val repository: GenRepository //abstract way of obtaining a repository 

} 

//concrete implementation for entity 
trait EntityImplModule extends EntityModule { this: CoreModule => 
    case class Entity(val id: Id) extends GenEntity 

    def mkEntity(id: Id) = Entity(id) 
} 

//modules that provides a concrete implementation for GenRepository 
trait RepositoryImplModule extends RepositoryModule { this: CoreModule with EntityModule => 

    object RepositoryImpl extends GenRepository { 
     def getById(id: Id) = mkEntity(id) 
    } 

} 

//this unifies all your modules. You can also bind any dependencies and specify any types 
object Universe 
    extends CoreModule 
    with EntityImplModule 
    with RepositoryImplModule { 

    type Id = java.util.UUID 

    val repository = RepositoryImpl 

    def mkEntity(id: Id) = Entity(id) 

} 

//usage 
object Main { 

    import Universe._ 
    import java.util.UUID 

    val entity = repository.getById(UUID.randomUUID()) 
    println(entity.id) 

} 

這實現了創建實施獨立於具體類型ID中的你的目標,它也提供了一個很好的方式來做依賴注入。

例如,爲GenRepository提供具體實現的模塊可能需要Id的具體類型。您可以很好地創建另一個模塊,將Id綁定到具體類型,並使RepositoryImplModule依賴於前一個模塊,從而指定GenRepository的此具體實現僅適用於某種類型的ID。

蛋糕模式是非常強大的,有很多變化。此視頻解釋了它相當不錯,我建議你看它,如果你有興趣在此解決方案:

Cake Pattern: The Bakery from the Black Lagoon

+0

這是一個更好的解決方案,原因很簡單,您可以完全避免「Gen」爆炸。 –