几周前我开始使用Scala
。总的来说,我非常喜欢这种语言为开发人员提供的所有功能,但有时很难从Java
习惯转换。
这个问题与特质有关。目前几乎每次我都会看到我将提取到Java
中不同类的逻辑的一部分,并将构造函数参数添加到依赖类我转而创建特征并将其混合到我的类中。 (如果你只有一把锤子,一切看起来像钉子)
但我发现我的方法存在两个问题。
测试具有混合特征的类:
在Java
如果我有class Foo
使用Bar
和Baz
类,我可能会将它们注入我的Foo
课程并使用它们。如果我使用特征这样做,我将class Foo extends Bar with Baz
。
现在在我的测试中,我必须编写类似
的内容trait BarMock extends Bar{
override def bar = "barMock"
}
trait BazMock extends Baz{
override def baz = "bazMock"
}
val foo = new Foo with BarMock with BazMock
如果我想交换一些特质行为的实现。也许只是我用来写作
Bar bar = mock(Bar.class);
when(bar.bar()).thenReturn("barMock");
Baz baz = mock(Baz.class);
when(baz.baz()).thenReturn("bazMock");
Foo foo = new Foo(bar, baz);
我在Scala项目中展示的模拟特征是否正常?或者我应该限制自己在测试中混淆嘲弄的特征。
特质方法可见性
这也与我目前对特质的痴迷有关。在Java
中,如果我将Bar, Baz
实例注入Foo
实例,我不会自动将Bar, Baz
中的所有公共方法添加到Foo
接口。如果我想这样做,我必须手工添加每个委托方法。如果我正在使用特征,当我混合一些特征时,我会自动“污染”Foo
界面中的特征方法。有没有什么方法可以实现C++
的私有继承?
我想到的唯一解决方案是将特征方法声明为protected
并将特征标记为包私有。这种方法在Foo
中可见,但在包外,有人无法写val bar:Bar = new Foo
。此外,如果我理解正确,只有当包私有特征源代码将在我的项目中时才会验证包私有约束,因为JVM
无法表示包私有的概念,编译器只是在字节码中公开它。
答案 0 :(得分:1)
总之:蛋糕。蛋糕模式。关于它的文章已经写得很多,最边缘,但是一旦这个概念点击了你的脑海,它很容易实现。它是实现SOLID以及可测试性和静态类型依赖注入以及混合和匹配组件化代码的绝佳工具。
它有一个代价,但我曾经觉得价格需要一个特定的理由来使用Cake代码的给定位,我现在看到它反过来了。你应该根据具体情况证明不使用它。
关于蛋糕的开创性论文是Scalable Component Abstractions(这是一个付费专区,但在“网络”的其他地方可以免费获得)。尽管如此,与大多数此类事情一样,这不是最佳起点。只需在网上搜索" Scala Cake Pattern"产生许多命中。阅读一些内容,直到找到一个能够让你明白的东西......