面向Java开发人员的Scala指南: 增强Scitter库

欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入

兼容性

但是,这又产生一个有趣的问题:从 Java 代码调用这个方法有多容易?毕竟,如果这个库的主要目标之一是维护与 Java 代码的兼容性,那么我们需要确保 Java 代码在使用它时不至于太麻烦。

我们首先通过我们的好朋友 javap 检验一下 Scitter 类:

清单 10. 哦,没错,Java 代码……我现在想起来了……

C:\&;javap -classpath classes com.tedneward.scitter.ScitterCompiled from “scitter.scala”public class com.tedneward.scitter.Scitter extends java.lang.Object implements scala.ScalaObject{ public com.tedneward.scitter.Scitter(java.lang.String, java.lang.String); public scala.List friendsTimeline(scala.Seq); public boolean verifyCredentials(); public int $tag() throws java.rmi.RemoteException;}

这时我心中有两点担心。首先,friendsTimeline() 带有一个 scala.Seq 参数(这是我们刚才用过的重复参数特性)。其次,friendsTimeline() 方法和 Scitter 对象中的 publicTimeline() 方法一样(如果不信,可以运行 javap 查证),返回一个元素列表 scala.List.这两种类型在 Java 代码中有多好用?

最简单的方法是用 Java 代码而不是 Scala 编写一组小型的 JUnit 测试,所以接下来我们就这样做。虽然可以测试 Scitter 实例的构造,并调用它的 verifyCredentials() 方法,但这些并不是特别有用 ― 记住,我们不是要验证 Scitter 类的正确性,而是要看看从 Java 代码中使用它有多容易。为此,我们直接编写一个测试,该测试将获取 “friends timeline” ― 换句话说,我们要实例化一个 Scitter 实例,并且不使用任何参数来调用它的 friendsTimeline() 方法。

这有点复杂,因为需要传入 scala.Seq 参数 ― scala.Seq 是一个 Scala 特性,它将映射到底层 JVM 中的一个接口,所以不能直接实例化。我们可以尝试典型的 Java null 参数,但是这样做会在运行时抛出异常。我们需要的是一个 scala.Seq 类,以便从 Java 代码中轻松地实例化这个类。

最终,我们还是在 mutable.ListBuffer 类型中找到一个这样的类,这正是在 Scitter 实现本身中使用的类型:

清单 11. 现在我明白了自己为什么喜欢 Scala……

package com.tedneward.scitter.test;import org.junit.*;import com.tedneward.scitter.*;public class JavaScitterTests{ public static final String testUser = “TESTUSER”; public static final String testPassword = “TESTPASSWORD”; @Test public void getFriendsStatuses() { Scitter scitter = new Scitter(testUser, testPassword); if (scitter.verifyCredentials()) { scala.List statuses = scitter.friendsTimeline(new scala.collection.mutable.ListBuffer()); Assert.assertTrue(statuses.length() > 0); } else Assert.assertTrue(false); }}

使用返回的 scala.List 不是问题,因为我们可以像对待其他 Collection 类一样对待它(不过我们的确怀念 Collection 的一些优点,因为 List 上基于 Scala 的方法都假设您将从 Scala 中与它们交互),所以,遍历结果并不难,只要用上一点 “旧式” Java 代码(大约 1995 年时候的风格):

清单 12. 重回 1995,又见 Vector……

package com.tedneward.scitter.test;import org.junit.*;import com.tedneward.scitter.*;public class JavaScitterTests{ public static final String testUser = “TESTUSER”; public static final String testPassword = “TESTPASSWORD”; @Test public void getFriendsStatuses() { Scitter scitter = new Scitter(testUser, testPassword); if (scitter.verifyCredentials()) { scala.List statuses = scitter.friendsTimeline(new scala.collection.mutable.ListBuffer()); Assert.assertTrue(statuses.length() > 0); for (int i=0; i<statuses.length(); i++) { Status stat = (Status)statuses.apply(i); System.out.println(stat.user().screenName() + ” said ” + stat.text()); } } else Assert.assertTrue(false); }}

这将我们引向另一个部分,即将参数传递到 friendsTimeline() 方法。不幸的是,ListBuffer 类型不是将一个集合作为构造函数参数,所以我们必须构造参数列表,然后将集合传递到方法调用。这样有些单调乏味,但还可以承受:

清单 13. 现在可以回到 Scala 吗?

package com.tedneward.scitter.test;import org.junit.*;import com.tedneward.scitter.*;public class JavaScitterTests{ public static final String testUser = “TESTUSER”; public static final String testPassword = “TESTPASSWORD”; // … @Test public void getFriendsStatusesWithCount() { Scitter scitter = new Scitter(testUser, testPassword); if (scitter.verifyCredentials()) { scala.collection.mutable.ListBuffer params = new scala.collection.mutable.ListBuffer(); params.$plus$eq(new Count(5)); scala.List statuses = scitter.friendsTimeline(params); Assert.assertTrue(statuses.length() > 0); Assert.assertTrue(statuses.length() == 5); for (int i=0; i<statuses.length(); i++) { Status stat = (Status)statuses.apply(i); System.out.println(stat.user().screenName() + ” said ” + stat.text()); } } else Assert.assertTrue(false); }}

所以,虽然 Java 版本比对应的 Scala 版本要冗长一点,但是到目前为止,从任何要使用 Scitter 库的 Java 客户机中调用该库仍然非常简单。好极了。

结束语

显然,对于 Scitter 还有很多事情要做,但是它已经逐渐丰满起来,感觉不错。我们设法对 Scitter 库的通信部分进行了 DRY 化处理,并且为 Twitter 提供的很多不同的 API 调用合并了所需的可选参数 ― 到目前为止,Java 客户机基本上没有受到我们公布的 API 的拖累。即使 API 没有 Scala 所使用的那些 API 那样干净,但是如果 Java 开发人员要使用 Scitter 库,也不需要费太多力气。

Scitter 库仍然带有对象的意味,不过我们也开始看到,一些有实用意义的 Scala 特性正在出现。随着我们继续构建这个库,只要有助于使代码更简洁、更清晰,越来越多这样的特性将添加进来。本应如此。

是时候说再见了,我要短暂离开一下。等我回来时,我将为这个库增加对离线测试的支持,并增加更新用户状态的功能。到那时,Scala 迷们,请记住:功能正常总比功能失常好。(对不起,我只是太喜欢开玩笑了。)

[1][2][3][4]

幸福不是因为你拥有得多,而是由于你计较得少。

面向Java开发人员的Scala指南: 增强Scitter库

相关文章:

你感兴趣的文章:

标签云: