栏目导航
热点推荐
- 三十条有用的 Java 编程规则
- Java制作水印图片源码
- Java常见异常及可能的导致原因
- Java中的修饰词使用方法总结
- J2EE系统异常的处理准则
- Java中的异常、断言、日志解析(
- Java面试技巧:Java面试题集锦(
- 面向Java开发人员的Scala指南:
- Java程序员:一刻钟精通正则表达
- 网友经验分享:学好java开发的关
- 专家解答:创建表格与数据库进行
- Java远程访问Domino数据库
阅览排行
面向Java开发人员的Scala指南: 增强Scitter库
www.jz123.cn 2009-09-03 来源: IT专家网 责任编辑(袁袁) 我要投递新闻
Twitter API 表明,friends_timeline API 调用 “返回认证用户和该用户的朋友发表的最近 20 条状态”。(它还指出,对于直接从 Twitter Web 站点使用 Twitter 的用户,“这相当于 Web 上的 ‘/home’”。)对于任何 Twitter API 来说,这是非常基本的要求,所以让我们将它添加到 Scitter 类中。之所以将它添加到类而不是对象中,是因为正如文档中指出的那样,这是以验证用户的身份做的事情,而我已经决定归入 Scitter 类,而不是 Scitter 对象。
但是,这里我们碰到一块绊脚石:friends_timeline 调用接受一组 “可选参数”,包括 since_id、max_id、count 和 page,以控制返回的结果。这是一项比较复杂的操作,因为 Scala 不像其他语言(例如 Groovy、JRuby 或 JavaScript)那样原生地支持 “可选参数” 的思想,但是我们首先来处理简单的东西 — 我们来创建一个 friendsTimeline 方法,该方法只执行一般的、非参数化的调用:
清单 6.“告诉我你身边的朋友是怎样的……”
package com.tedneward.scitter { class Scitter { def friendsTimeline : List[Status] = { val (statusCode, statusBody) = Scitter.execute("http://twitter.com/statuses/friends_timeline.xml", username, password) if (statusCode == 200) { val responseXML = XML.loadString(statusBody) val statusListBuffer = new ListBuffer[Status] for (n <- (responseXML \ "status").elements) statusListBuffer += (Status.fromXml(n)) statusListBuffer.toList } else { Nil } } } } |
到目前为止,一切良好。用于测试的相应方法看上去如下所示:
清单 7. “我能判断您是怎样的人 ”(Miguel de Cervantes)
package com.tedneward.scitter.test { class ScitterTests { // ... @Test def scitterFriendsTimeline = { val scitter = new Scitter(testUser, testPassword) val result = scitter.friendsTimeline assertTrue(result.length > 0) } } } |
好极了。看上去就像 Scitter 对象中的 publicTimeline() 方法,并且行为也几乎完全相同。
对于我们来说,那些可选参数仍然有问题。因为 Scala 并没有可选参数这样的语言特性,乍一看来,惟一的选择就是完整地创建重载的 friendsTimeline() 方法,让该方法带有一定数量的参数。
幸运的是,还有一种更好的方式,即通过一种有趣的方式将 Scala 的两个语言特性(有一个特性我还没有提到过) — case 类和 “重复参数” 结合起来(见清单 8):
清单 8. “我有多爱你?……”
package com.tedneward.scitter { // ... abstract class OptionalParam case class Id(id : String) extends OptionalParam case class UserId(id : Long) extends OptionalParam case class Since(since_id : Long) extends OptionalParam case class Max(max_id : Long) extends OptionalParam case class Count(count : Int) extends OptionalParam case class Page(page : Int) extends OptionalParam class Scitter(username : String, password : String) { // ... def friendsTimeline(options : OptionalParam*) : List[Status] = { val optionsStr = new StringBuffer("http://twitter.com/statuses/friends_timeline.xml?") for (option <- options) { option match { case Since(since_id) => optionsStr.append("since_id=" + since_id.toString() + "&") case Max(max_id) => optionsStr.append("max_id=" + max_id.toString() + "&") case Count(count) => optionsStr.append("count=" + count.toString() + "&") case Page(page) => optionsStr.append("page=" + page.toString() + "&") } } val (statusCode, statusBody) = Scitter.execute(optionsStr.toString(), username, password) if (statusCode == 200) { val responseXML = XML.loadString(statusBody) val statusListBuffer = new ListBuffer[Status] for (n <- (responseXML \ "status").elements) statusListBuffer += (Status.fromXml(n)) statusListBuffer.toList } else { Nil } } } } |
看到标在选项参数后面的 * 吗?这表明该参数实际上是一个参数序列,这类似于 Java 5 中的 varargs 结构。和 varargs 一样,传递的参数数量可以像前面那样为 0(不过,我们将需要回到测试代码,向 friendsTimeline 调用增加一对括号,否则编译器无法作出判断:是调用不带参数的方法,还是出于部分应用之类的目的而调用该方法);我们还可以开始传递那些 case 类型,如下面的清单所示:
清单 9. “……听我细细说”(William Shakespeare)
package com.tedneward.scitter.test { class ScitterTests { // ... @Test def scitterFriendsTimelineWithCount = { val scitter = new Scitter(testUser, testPassword) val result = scitter.friendsTimeline(Count(5)) assertTrue(result.length == 5) } } } |
当然,总是存在这样的可能性:客户机传入古怪的参数序列,例如 friendsTimeline(Count(5), Count(6), Count(7)),但是在这里,我们只是将列表传递给 Twitter(希望它们的错误处理足够强大,能够只采用指定的最后那个参数)。当然,如果真的担心这一点,也很容易在构造发送到 Twitter 的 URL 之前,从头至尾检查重复参数列表,并采用指定的每种参数的最后一个参数。不过,后果自负
上一篇:Java Math 类中的新功能(一): 实数 下一篇:通过Java或Jsp向数据库存取二进制图片