我正在阅读“Scala in depth”一书的第一部分。在第一部分中,它给出了一个将java JdbcTemplate接口转换为scala:
的示例Java代码:
public interface JdbcTemplate {
List query(PreparedStatementCreator psc,
RowMapper rowMapper)
}
Scala代码:
trait JdbcTemplate {
def query[ResultItem](psc : Connection => PreparedStatement,
rowMapper : (ResultSet, Int) => ResultItem) : List[ResultItem]
}
然后它说:
通过一些简单的转换,我们创建了一个直接与函数相关的接口。这是一种更具功能性的方法,因为scala的功能特性允许组合。当你读完这本书时,你将能够完全不同地接近这个界面的设计。
我无法理解“traits allow composition”,因为我在提供的示例中找不到任何“组合”。
我会错过什么吗?
答案 0 :(得分:3)
你错过了这句话的第一部分:
scala的功能特征允许合成
在scala函数中是一个简单的对象,由Function[-T, +R]
等特征构成,在所有这些特征上,你有两种方法:andThen
和compose
。
答案 1 :(得分:1)
您的代码段不是组合样本,但允许进行合成。事实上,仅trait
只能构成......本身:)
Trait允许在运行时通过with
关键字进行撰写
基本上,它允许将特征的方法添加到关联的trait
或class
甚至...运行时对象!
已知组合是运行时特征(其主要优点),并且已知继承是编译特征,因此是静态的。
以下是在运行时使用trait
组合的示例:
val obj1 = new MyClass() with JdbcTemplate
//obj1.query .......
与Java相比,如果MySuperClass
是class
或abstract class
,您仍然可以通过实施某种策略模式等在运行时从其他地方添加/更改行为......但是它需要你描述一个接口+实现。硼
相反,Trait
允许在一个地方定义方法。
这就是为什么在scala中,trait
被称为“允许组合”,显然,函数式编程概念更适合于组合而不是继承。
更新----------------------
@Alexlv是对的=>重要的一个词是Scala的 FUNCTION 特征。
我的上述解释仍然正确,但不符合作者的意思
恕我直言,他想说:Connection => PreparedStatement
是一个Function1
,并且由于函数喜欢组合,它可以从函数式编程字中提供一些很好的处理,以生成所需的query
方法参数。
答案 2 :(得分:0)
作者的观点是用函数类型替换PreparedStatementCreator
和RowMapper
会产生更多功能的API(惊喜!)。 API更好地支持代码重用,因为psc
和rowMapper
函数可以由简单的功能组件组成。例如,您可能拥有filter
ResultSet
,提取各种数据,转换数据(map
),汇总数据(fold
)等功能。
正如@Alexiv指出的那样,所有Scala函数对象(通过各种Function
特征)都提供了支持函数组合的andThen
和compose
方法。