抽象地談論 Scala 的確有趣
歡迎回來
我們對於 Scitter 有幾個目標
● 簡化 Twitter 訪問
● 可以從 Java 客戶機輕松訪問它
● 輕松模擬以便進行測試
在這一期
到目前為止
首先我們簡單回顧一下到目前為止我們所處的階段
清單
package com
{
import mons
import scala
/**
* Status message type
* sent back from Twitter (usually in some kind of collection form)
* that all optional elements in the Status type are represented by the
* Scala Option[T] type
*/
abstract class Status
{
/**
* Nested User type
* if we decide later that it
* elements
* tad circular)
*/
abstract class User
{
val id : Long
val name : String
val screenName : String
val description : String
val location : String
val profileImageUrl : String
val url : String
val protectedUpdates : Boolean
val followersCount : Int
}
/**
* Object wrapper for transforming (format) into User instances
*/
object User
{
/*
def fromAtom(node : Node) : Status =
{
}
*/
/*
def fromRss(node : Node) : Status =
{
}
*/
def fromXml(node : Node) : User =
{
new User {
val id = (node \
val name = (node \
val screenName = (node \
val description = (node \
val location = (node \
val profileImageUrl = (node \
val url = (node \
val protectedUpdates = (node \
val followersCount = (node \
}
}
}
val createdAt : String
val id : Long
val text : String
val source : String
val truncated : Boolean
val inReplyToStatusId : Option[Long]
val inReplyToUserId : Option[Long]
val favorited : Boolean
val user : User
}
/**
* Object wrapper for transforming (format) into Status instances
*/
object Status
{
/*
def fromAtom(node : Node) : Status =
{
}
*/
/*
def fromRss(node : Node) : Status =
{
}
*/
def fromXml(node : Node) : Status =
{
new Status {
val createdAt = (node \
val id = (node \
val text = (node \
val source = (node \
val truncated = (node \
val inReplyToStatusId =
if ((node \
Some((node \
else
None
val inReplyToUserId =
if ((node \
Some((node \
else
None
val favorited = (node \
val user = User
}
}
}
/**
* Object for consuming
* Use this to do non
*/
object Scitter
{
/**
* Ping the server to see if it
*
* Twitter docs say:
* test
* Returns the string
* URL:
* Formats: xml
* Method(s): GET
*/
def test : Boolean =
{
val client = new HttpClient()
val method = new GetMethod(
method
new DefaultHttpMethodRetryHandler(
client
val statusLine = method
statusLine
}
/**
* Query the public timeline for the most recent statuses
*
* Twitter docs say:
* public_timeline
* Returns the
* a custom user icon
* public timeline is cached for
* that is a waste of resources
* URL: _timeline
* Formats: xml
* Method(s): GET
* API limit: Not applicable
* Returns: list of status elements
*/
def publicTimeline : List[Status] =
{
import llection
val client = new HttpClient()
val method = new GetMethod(
method
new DefaultHttpMethodRetryHandler(
client
val statusLine = method
if (statusLine
{
val responseXML =
XML
val statusListBuffer = new ListBuffer[Status]
for (n <
statusListBuffer += (Status
statusListBuffer
}
else
{
Nil
}
}
}
/**
* Class for consuming
* thus
* behave accordingly (according to the Twitter API documentation)
*/
class Scitter(username : String
{
/**
* Verify the user credentials against Twitter
*
* Twitter docs say:
* verify_credentials
* Returns an HTTP
* requesting user if authentication was successful; returns a
* code and an error message if not
* user credentials are valid
* URL: _credentials
* Formats: xml
* Method(s): GET
*/
def verifyCredentials : Boolean =
{
val client = new HttpClient()
val method = new GetMethod(
method
new DefaultHttpMethodRetryHandler(
client
val creds = new UsernamePasswordCredentials(username
client
new AuthScope(
client
val statusLine = method
statusLine
}
}
}
代碼有點長
● case 類 User 和 Status
● 一個 Scitter 獨立對象
● 一個 Scitter 實例(用 username 和 password 參數化)
到目前為止
顯然
連接
對於代碼
實際上
清單
package com
{
//
object Scitter
{
//
private[scitter] def exec ute(url : String) =
{
val client = new HttpClient()
val method = new GetMethod(url)
method
new DefaultHttpMethodRetryHandler(
client
(method
}
}
}
注意兩點
由於使用元組
清單
package com
{
//
object Scitter
{
/**
* Ping the server to see if it
*
* Twitter docs say:
* test
* Returns the string
* URL:
* Formats: xml
* Method(s): GET
*/
def test : Boolean =
{
val (statusCode
execute(
statusCode ==
}
}
}
實際上
注意
接下來
(順便說一句
順便說一句
清單
package com
{
//
object Scitter
{
//
private[scitter] def execute(url : String
{
val client = new HttpClient()
val method = new GetMethod(url)
method
new DefaultHttpMethodRetryHandler(
client
client
new AuthScope(
new UsernamePasswordCredentials(username
client
(method
}
}
}
實際上
清單
package com
{
//
object Scitter
{
//
private[scitter] def execute(url : String) : (Int
execute(url
private[scitter] def execute(url : String
{
val client = new HttpClient()
val method = new GetMethod(url)
method
new DefaultHttpMethodRetryHandler(
if ((username !=
{
client
client
new AuthScope(
new UsernamePasswordCredentials(username
}
client
(method
}
}
}
到目前為止
連接(到朋友)
Twitter API 表明
但是
清單
package com
{
class Scitter
{
def friendsTimeline : List[Status] =
{
val (statusCode
Scitter
username
if (statusCode ==
{
val responseXML = XML
val statusListBuffer = new ListBuffer[Status]
for (n <
statusListBuffer += (Status
statusListBuffer
}
else
{
Nil
}
}
}
}
到目前為止
清單
package com
{
class ScitterTests
{
//
@Test def scitterFriendsTimeline =
{
val scitter = new Scitter(testUser
val result = scitter
assertTrue(result
}
}
}
好極了
對於我們來說
幸運的是
清單
package com
{
//
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
{
//
def friendsTimeline(options : OptionalParam*) : List[Status] =
{
val optionsStr =
new StringBuffer(
for (option <
{
option match
{
case Since(since_id) =>
optionsStr
case Max(max_id) =>
optionsStr
case Count(count) =>
optionsStr
case Page(page) =>
optionsStr
}
}
val (statusCode
Scitter
if (statusCode ==
{
val responseXML = XML
val statusListBuffer = new ListBuffer[Status]
for (n <
statusListBuffer += (Status
statusListBuffer
}
else
{
Nil
}
}
}
}
看到標在選項參數後面的 * 嗎?這表明該參數實際上是一個參數序列
清單
package com
{
class ScitterTests
{
//
@Test def scitterFriendsTimelineWithCount =
{
val scitter = new Scitter(testUser
val result = scitter
assertTrue(result
}
}
}
當然
兼容性
但是
我們首先通過我們的好朋友 javap 檢驗一下 Scitter 類
清單
C:\>javap
Compiled from
public class com
cala
public com
public scala
public boolean verifyCredentials();
public int $tag() throws java
}
這時我心中有兩點擔心
最簡單的方法是用 Java 代碼而不是 Scala 編寫一組小型的 JUnit 測試
這有點復雜
最終
清單
package com
import org
import com
public class JavaScitterTests
{
public static final String testUser =
public static final String testPassword =
@Test public void getFriendsStatuses()
{
Scitter scitter = new Scitter(testUser
if (scitter
{
scala
scitter
Assert
}
else
Assert
}
}
使用返回的 scala
清單
package com
import org
import com
public class JavaScitterTests
{
public static final String testUser =
public static final String testPassword =
@Test public void getFriendsStatuses()
{
Scitter scitter = new Scitter(testUser
if (scitter
{
scala
scitter
Assert
for (int i=
{
Status stat = (Status)statuses
System
}
}
else
Assert
}
}
這將我們引向另一個部分
清單
package com
import org
import com
public class JavaScitterTests
{
public static final String testUser =
public static final String testPassword =
//
@Test public void getFriendsStatusesWithCount()
{
Scitter scitter = new Scitter(testUser
if (scitter
{
llection
new llection
params
scala
Assert
Assert
for (int i=
{
Status stat = (Status)statuses
System
}
}
else
Assert
}
}
所以
結束語
顯然
Scitter 庫仍然帶有對象的意味
是時候說再見了
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19590.html