Ale*_*ean 6 scala fluent-interface
我一直在阅读关于Java,JavaScript和Scala中的OO'流畅的界面'方法,我喜欢它的外观,但一直在努力寻找如何在Scala中使用更基于类型/功能的方法来协调它.
给出一个非常具体的例子:我编写了一个API客户端,可以像这样调用:
val response = MyTargetApi.get("orders", 24)
Run Code Online (Sandbox Code Playgroud)
返回值get()是一个Tuple3名为的类型RestfulResponse,在我的包对象中定义:
// 1. Return code
// 2. Response headers
// 2. Response body (Option)
type RestfulResponse = (Int, List[String], Option[String])
Run Code Online (Sandbox Code Playgroud)
这工作正常 - 我真的不想牺牲元组返回值的功能简单性 - 但我想用各种'流畅'方法调用来扩展库,可能是这样的:
val response = MyTargetApi.get("customers", 55).throwIfError()
// Or perhaps:
MyTargetApi.get("orders", 24).debugPrint(verbose=true)
Run Code Online (Sandbox Code Playgroud)
如何将get()返回类型元组(或类似元组)的功能简单性与为我的API添加更多"流畅"功能的能力相结合?
您似乎正在处理休息样式通信的客户端API.您的get方法似乎是触发实际请求/响应周期的方法.看起来你必须处理这个问题:
我认为对于传输的属性,您可以将其中的一些放入MyTargetApi对象的构造函数中,但您也可以创建一个查询对象来存储单个查询的查询对象,并且可以使用方法以流畅的方式进行设置query():
MyTargetApi.query().debugPrint(verbose=true).throwIfError()
Run Code Online (Sandbox Code Playgroud)
这将返回一些有状态Query对象,该对象存储日志级别的值,错误处理.为了提供输入的数据,您还可以使用查询对象来设置这些值,但不是返回您的响应,而是返回QueryResult:
class Query {
def debugPrint(verbose: Boolean): this.type = { _verbose = verbose; this }
def throwIfError(): this.type = { ... }
def get(tpe: String, id: Int): QueryResult[RestfulResponse] =
new QueryResult[RestfulResponse] {
def run(): RestfulResponse = // code to make rest call goes here
}
}
trait QueryResult[A] { self =>
def map[B](f: (A) => B): QueryResult[B] = new QueryResult[B] {
def run(): B = f(self.run())
}
def flatMap[B](f: (A) => QueryResult[B]) = new QueryResult[B] {
def run(): B = f(self.run()).run()
}
def run(): A
}
Run Code Online (Sandbox Code Playgroud)
然后最终得到你打电话的结果run.所以在一天结束时你可以这样称呼它:
MyTargetApi.query()
.debugPrint(verbose=true)
.throwIfError()
.get("customers", 22)
.map(resp => resp._3.map(_.length)) // body
.run()
Run Code Online (Sandbox Code Playgroud)
这应该是一个冗长的请求,将在问题上出错,检索id为22的客户,保持身体并获得其长度Option[Int].
这个想法是你可以map用来定义你还没有的结果的计算.如果我们添加flatMap它,那么您还可以组合来自两个不同查询的两个计算.
| 归档时间: |
|
| 查看次数: |
2197 次 |
| 最近记录: |