将类作为函数,并使用函数类型声明参数类型是否很好?

时间:2014-08-21 04:37:16

标签: scala testing functional-programming

我正在开发一个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)

我正在努力解决这两个问题。在函数风格中编写代码时,这是一个常见的模式吗?是否有任何开源项目采用这种风格,我可以从中获得一些想法?

2 个答案:

答案 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快捷方式来定位实现子类。