我是学习Scala的新手。这段代码出现在Scala in Action中。我有几个问题。
trait ReadOnly {
val underlying: MongoDBCollection
def name = underlying getName
def fullName = underlying getFullName
def find(query: Query): DBCursor = {
def applyOptions(cursor:DBCursor, option: QueryOption): DBCursor = {
option match {
case Skip(skip, next) => applyOptions(cursor.skip(skip), next)
case Sort(sorting, next)=> applyOptions(cursor.sort(sorting), next)
case Limit(limit, next) => applyOptions(cursor.limit(limit), next)
case NoOption => cursor
}
}
applyOptions(find(query.q), query.option)
}
def find(doc: DBObject): DBCursor = underlying find doc
def findOne(doc: DBObject) = underlying findOne doc
def findOne = underlying findOne
def getCount(doc: DBObject) = underlying getCount doc
}
1)本节讨论重载函数。在其中我看到find
超载。但是,我从来没有见过像这样构建的方法:def find(doc: DBObject): DBCursor = underlying find doc
。我只见过这样定义的方法:def find(doc: DBObject): DBCursor = { ... }
。怎么能在括号中没有东西的情况下发现超载?它在做什么?
2)本书的这一部分说明了上面的代码,
在这里,您使用模式匹配将每个查询选项应用于 find方法返回的结果 - 在本例中为DBCursor。
我知道DBCursor
是返回类型,从我最近阅读的Android编程书中我知道游标是一种包含数据的对象。我想知道的是,这是指哪种查找方法,并且不仅仅是DBCursor
返回的对象类型的名称而不是实际对象的名称?
3)这本书继续说
嵌套的applyOptions函数是递归应用的,因为每个函数都是如此 查询选项可以包装下一个标识的另一个查询选项 变量,当它与NoOption匹配时你会拯救。
我不明白当它说什么时它会说什么?每个查询都可以包含另一个查询"有几个原因。我对这个'包裹'有点困惑。使用的术语,但更大的问题是如何有多个查询可用于包装另一个查询?关于applyOptions
它所指的是什么,它也有点含糊不清。
4)代码的match
部分是如何实现的?我知道您可以将参数传递给方法,但match
是嵌套的,那么它如何接收大小写匹配的参数呢?
答案 0 :(得分:0)
Scala方法语法
您可能习惯使用Java,其中方法代码总是在一对花括号内。但这在Scala中是不同的,其中方法体只是一个表达式 - 评估某个值的东西(也可能有一些副作用)。恰好在Scala中,代码块也是一个有效的表达式,可以用作方法体。
您可能会问:等待,如果表达式是具有值且块是表达式的东西,那么块的值是什么?
在Scala中,块的“值”是该块中最后一个表达式的值。
例如,find(query: Query)
方法的正文值将为applyOptions(find(query.q), query.option)
- 这是“返回”值。
<强> DBCursor 强>
在MongoDB中,游标是某种迭代器,可以用来懒惰地从数据库中获取数据。在您的示例中,DBCursor
是find
方法(两者)返回的对象类型的名称。我不明白你的意思是“实际对象的名字”。
QueryOption包装
仔细阅读 - 作者没有说“查询可以包装另一个查询” - 他说“查询选项可以包装另一个查询选项”。只有一个查询,可能有多个选项,这些选项使用递归结构表示,其中每个选项包含另一个选项,例如
Limit(100, Skip(200, Sort(<sorting>, NoOption)))
applyOption
函数通过查看其当前选项,对游标应用适当的操作并继续执行下一个(包装)选项直到最终到达NoOption
来完成该嵌套结构。
模式匹配
case Skip(skip, next)
可能看起来像一个方法调用,但它不是 - 它只是类似的语法。实际上,它与方法调用完全相反,因为在这里我们不是在某处传递某些参数,而是从某个地方取出一些参数。每个案例都试图解构我们的QueryOption
对某些模式。例如,当我们说case Skip(skip, next) => some code
时,我们实际上会说:“当我们的选项为Skip
时,请将跳过的文档数量从其中调出并称之为skip
。另外,请执行当前选项中的next(wrapped)选项并将其命名为next
。然后,使用skip
和next
执行某些操作。“
希望这会带来一些澄清。