【发布时间】:2012-03-13 10:31:42
【问题描述】:
有没有办法使用 Scala 的类型系统来简洁地指定完整对象图的上下文相关子图?
DCI 认为您通常拥有一个相当复杂的对象图,但在任何一个用例中,您通常只想使用子图。你有一个Foo,它有一个Bar和一个Bat,但是当你在用例1中时,你只关心Bar,而在用例2中时,只关心@987654325 @。
例如,假设您有这个结构,角色 1 用例需要 Foo->Bar->Baz->Bin,角色 2 用例需要 Foo->Bat->Baz->Buz:
class Foo{
val bar = new Bar() //Only relevant to Role 1
val bat = new Bat() //Only relevant to Role 2
}
class Bar {
val baz = new Baz()
}
class Bat {
val baz = new Baz()
}
//Relevant to both Role 1 and 2 (via Bar or Bat)
class Baz {
val bin = new Bin() //Only relevant to Role 1
val buz = new Buz() //Only relevant to Role 2
}
class Bin{}
class Buz{}
很容易看出如何通过使用特征来限制单个类中的访问:
trait FooInRole1 { def bar : Bar } //Define accessor in trait
s/Foo/Foo extends FooInRole1/ //Change Foo's declaration to implement trait
val f : FooInRole1 = new Foo //LHS is i'face, RHS is implementation
//f.bat <--Compile error Irrelevant field is not available. \o/
但是您必须为与用例相关的每个对象重复此模式。 (例如,你需要一个BazInRole1 来访问bin 和一个BazInRole2 来访问biz)
我的问题是,是否有某种方法可以避免编写所有这些容易出错、名称空间拥挤的特征。例如,我可以想象这样的代码(不能编译):
class Foo[T] {
T match {
case r1 : Role1 => def bar : Bar[T]
case r2 : Role2 => def bat : Bat[T]
case _ => //Nothing
}
}
val fInRole1 = new Foo[Role1] //Provides Foo->Bar->Baz->Bin
val fInRole2 = new Foo[Role2] //Provides Foo->Bat->Baz->Buz
似乎 Scala 的类型系统具有足够的表现力来做这样的事情,但我无法弄清楚。
【问题讨论】:
-
我认为这样的事情可以通过类型类来实现。只需使类型类成为对象图上的视图,并仅通过类型类访问和操作其内容。
标签: scala abstraction dci typeclass