Scala:继承与高阶函数
Scala: Inheritance vs Higher order function
假设,
class ClientFunc {
def client(s: String): Future[Service] = ....
def m1(s: String) = {
client(s).map( ...... )
}
...//there are multiple such methods like m1 in this class which
depends on "def client".
}
现在我们必须再添加一个相同类型但实现不同的客户端,我们希望根据需要将其与现有客户端一起使用。
所以有两种方法可以解决这个问题。
解决方案一:使用继承,例如在父级中使客户端方法抽象并为两个不同的客户端提供子级 classA 和 clientB 用于实现。
class clientA extends ClientFunc {
def client(s: String): Future[Service] = ....
}
class clientB extends ClientFunc {
def client(s: String): Future[Service] = ....
}
照常使用,
clientAInstance.m1("str")
and
clientBInstance.m1("str")
根据用例,我必须一次使用 clientA 和 clientB,因此我需要将两个客户端都注入服务中。
其他解决方案:通过使 "def m1" 之类的功能高阶并在其中传递客户端,保持 ClientFunc class 不变,为其他客户端添加一个功能,例如(def clientB),
class ClientFunc {
def clientA(s: String): Future[Service] = ....
def clientB(s: String): Future[Service] = ....
def m1(s: String, cl:String => Future[Service]) = {
cl(s).map( ...... )
}
}
现在每当我需要打电话时,我都会打电话,
ClientFuncInstance.m1("str", ClientFuncInstance.clientA)
and
ClientFuncInstance.m1("str", ClientFuncInstance.clientB)
不需要两次注入ClientFunc。
问题是在 Scala / 函数式编程中应该首选哪一种方式? & 为什么?如果还有其他更好的方法,请提出建议。
在我看来最好的方法是在构造函数中注入client
:
class ClientFunc(client: String => Future[Service]) {
def m1(s: String) = {
client(s).map( ...... )
}
...
}
您可以添加新的实现(包括用于测试的模拟)而无需更改现有代码。
[评论后更新]
你会这样使用它:
def clientA(s: String): Future[Service] = ....
def clientB(s: String): Future[Service] = ....
val clientFuncA = new ClientFunc(clientA)
val clientFuncB = new ClientFunc(clientB)
class Service(funcA: ClientFunc, funcB: ClientFunc) {
def flag = ...
def client = if (flag) { funcA } else { funcB }
def m1(s: String) = {
client.m1(s)
}
}
val service = new Service(clientFuncA, clientFuncB)
假设,
class ClientFunc {
def client(s: String): Future[Service] = ....
def m1(s: String) = {
client(s).map( ...... )
}
...//there are multiple such methods like m1 in this class which
depends on "def client".
}
现在我们必须再添加一个相同类型但实现不同的客户端,我们希望根据需要将其与现有客户端一起使用。
所以有两种方法可以解决这个问题。 解决方案一:使用继承,例如在父级中使客户端方法抽象并为两个不同的客户端提供子级 classA 和 clientB 用于实现。
class clientA extends ClientFunc {
def client(s: String): Future[Service] = ....
}
class clientB extends ClientFunc {
def client(s: String): Future[Service] = ....
}
照常使用,
clientAInstance.m1("str")
and
clientBInstance.m1("str")
根据用例,我必须一次使用 clientA 和 clientB,因此我需要将两个客户端都注入服务中。
其他解决方案:通过使 "def m1" 之类的功能高阶并在其中传递客户端,保持 ClientFunc class 不变,为其他客户端添加一个功能,例如(def clientB),
class ClientFunc {
def clientA(s: String): Future[Service] = ....
def clientB(s: String): Future[Service] = ....
def m1(s: String, cl:String => Future[Service]) = {
cl(s).map( ...... )
}
}
现在每当我需要打电话时,我都会打电话,
ClientFuncInstance.m1("str", ClientFuncInstance.clientA)
and
ClientFuncInstance.m1("str", ClientFuncInstance.clientB)
不需要两次注入ClientFunc。
问题是在 Scala / 函数式编程中应该首选哪一种方式? & 为什么?如果还有其他更好的方法,请提出建议。
在我看来最好的方法是在构造函数中注入client
:
class ClientFunc(client: String => Future[Service]) {
def m1(s: String) = {
client(s).map( ...... )
}
...
}
您可以添加新的实现(包括用于测试的模拟)而无需更改现有代码。
[评论后更新]
你会这样使用它:
def clientA(s: String): Future[Service] = ....
def clientB(s: String): Future[Service] = ....
val clientFuncA = new ClientFunc(clientA)
val clientFuncB = new ClientFunc(clientB)
class Service(funcA: ClientFunc, funcB: ClientFunc) {
def flag = ...
def client = if (flag) { funcA } else { funcB }
def m1(s: String) = {
client.m1(s)
}
}
val service = new Service(clientFuncA, clientFuncB)