我正在开发一个scala项目,我的同事更喜欢功能风格,并提出了一种组织代码的方法:将类定义为函数
以下是一个示例:
class FetchFeed extends (String => List[Feed]) {
def apply(url:String):List[Feed] = ???
}
当其他类需要此类时,将使用类型String => List[Feed]
class MyWork(fetchFeed: String => List[Feed])
然后在某个地方,将FetchFeed
传递给它:
val fetchFeed = new FetchFeed
val myWork = new MyWork(fetchFeed)
优点是我们可以通过传递函数轻松模拟FetchFeed
:
val myWork = new MyWork(_ => List(new Feed))
语法简单易读。
但是,当我看到MyWork
:
class MyWork(fetchFeed: String => List[Feed])
很难看出哪个课程会被传入,即使IDE无法帮助我。我们需要在代码库中搜索extends (String => List[Feed])
,或找到初始化new MyWork
的位置。
如果还有另一个扩展String => List[Feed]
但在MyWork
中从未使用过的类,那么这通常会让我感到困惑。
但是如果我们用真实的类型声明它:
class MyWork(fetchFeed: FetchFeed)
直接跳转到声明会更容易。但是在这种情况下,我们无法直接传递函数,而是需要:
val fetchFeed = mock[FetchFeed]
fetchFeed.apply(any[String]) returns List(new Feed)
val myWork = new MyWork(fetchFeed)
我正在努力解决这两个问题。在函数风格中编写代码时,这是一个常见的模式吗?是否有任何开源项目采用这种风格,我可以从中获得一些想法?
答案 0 :(得分:2)
由于您提到的问题,您所描述的风格并不常见。如果你试图实现一种功能风格,那么最好只使用带有别名类型的函数。
// Alias the function type to a meaningful name
type FetchFeed = String => List[Feed]
// Declaring an implementation
val fetchFeed: FetchFeed = url => ...
// Nice type name to work with
class MyWork(fetchFeed: FetchFeed)
// Declaring a mock is still easy
new MyWork(_ => List(new Feed))
答案 1 :(得分:1)
Scala函数(A => B
)可以看作等同于定义单个apply(a: A): B
方法的Java接口。所以你所描述的风格基本上不同于:
这是完全标准的教科书Java风格,几乎是在Java发明之后。
回到我整天写Java的日子里,我记得通常使用Eclipses Show Type Hierarchy快捷方式来定位实现子类。