让我们假设我们有一个特征T
。实现以下目标的最佳方法是什么:
T
实现的每个人都应该被迫提供允许T
无参数初始化的可能性,即我们可能必须强制执行可配置工厂。< / LI>
A
的某个实现T
)的逻辑/数据应集中处理/存储,但应在工厂和{{{ 1}}。我认为实现这一目标的最简单/最简单的方法是为工厂添加特征并将A
链接到此工厂:
T
显然,这并没有真正“强制”执行工厂(只要有可用的替代实现),显然可以生成链接到“错误”trait T {
val factory: TFactory
}
trait TFactory {
def build(): T
val description: String // example for logic/data that only depend on the parameters
}
// example implementation:
class A(val factory: AFactory, paramA: Int, paramB: Int, paramC: Int) extends T
class AFactory(paramA: Int, paramB: Int, paramC: Int) extends TFactory {
def build = new A(this, paramA, paramB, paramC)
val description = f"$paramA $paramB $paramC"
}
的实例化A
1}}。我也不喜欢这种方法是重复初始化参数。我经常创建另一个类TFactory
,它再次包装所有参数(例如,以便于添加新参数)。因此,我最终得到了三个类,对于这个简单的问题,imho是很多样板。
我的问题是,是否存在(可能完全)不同的方法,它实现了相同的主要目标,但更简洁?
答案 0 :(得分:1)
我不太确定我是否完全满足您的要求,但您如何看待这种行为?
trait TFactory{
def build():T
val description:String
}
trait T extends TFactory
//can't declare A without build and not make it abstract
class A(paramA: Int, paramB: Int, paramC: Int) extends T {
def build = new A(paramA, paramB, paramC)
val description = f"$paramA $paramB $paramC"
}
val a1 = new A(1, 4, 5)
val a2 = a1.build()
//We can give ourselves as a factory to something that expects TFactory
val factory:TFactory = a1
val a_new = factory.build()
//More likely we can just give our build method
def func(f: ()=>T) = {
val new_t = f()
new_t
}
val a_newer = func(a1.build)
println(a1 +": " + a1.description)
println(a2 +": " + a2.description)
println(a_new +": " + a_new.description)
println(a_newer +": " + a_newer.description)
输出:
Main$$anon$1$A@69267649: 1 4 5
Main$$anon$1$A@69b1fbf4: 1 4 5
Main$$anon$1$A@24148662: 1 4 5
Main$$anon$1$A@3f829e6f: 1 4 5
答案 1 :(得分:1)
添加表示类型参数:
trait Factory[Prod] {
def build(): Prod
}
trait Prod[Repr] {
def factory: Factory[Repr]
}
或者,如果你想“强制执行”该类型保持不变(除非你从中获得某些东西,否则我不会这样做):
trait Prod[Repr <: Prod[Repr]] {
def factory: Factory[Repr]
}
然后:
case class AConfig(a: Int, b: Int)
case class A(config: AConfig) extends Prod[A] {
def factory = AFactory(config)
}
case class AFactory(config: AConfig) extends Factory[A] {
def build() = A(config)
}
val f0 = AFactory(AConfig(1, 2))
val p0 = f0.build()
val f1 = p0.factory
val p1 = f1.build()
assert(p0 == p1)