我真的是 scala 的新手,目前我正在浏览教程 ( https://docs.scala-lang.org/tour/variances.html )。
现在,查看一些库 (akka-http
),我偶然发现了一些这样的代码:
def fetchItem(itemId: Long): Future[Option[Item]] = Future {
orders.find(o => o.id == itemId)
}
而且我不太了解语法,或者更准确地说,= Future {
部分。据我所知,方法的语法是 def [methodName]([Arguments])(:[returnType]) = [codeblock]
。
然而,上面的内容似乎有所不同,因为它在“代码块”前面有 Future
。这是某种对象实例化吗?因为我找不到关于这种语法的文档,所以我在我的播放代码中尝试了这样的东西:
{
val myCat:Cat = new Cat("first cat")
val myOtherCat:Cat = Cat { "second cat" }
val myThirdCat:Cat = MyObject.getSomeCat
}
...
object MyObject
{
def getSomeCat: Cat = Cat
{
"blabla"
}
}
所有这些都有效,因为它创建了一个新的 Cat
对象。所以看起来 new Cat(args)
等同于 Cat { args }
。
但是 def getSomeCat: Cat = Cat
不应该用代码块定义一个方法,而不是实例化一个新的 Cat
对象吗?我很困惑。
最佳答案
我认为这里有两点:
1.
方法语法中的 [codeblock]
不必包含在 {} 中。如果只有一个表达式,则允许省略。
例如
def add(x: Int, y: Int) = x + y
或
def add(x: Int, y: Int) = Future { x + y }
2.
每个类都可以让其伴生对象定义一个 apply()
方法,无需显式声明“apply”(这是特殊的 Scala 语法糖)即可调用该方法。这允许我们通过遍历伴随对象来构造类的实例,并且由于可以省略“apply”,所以乍一看它看起来就像遍历类本身,只是没有“new”关键字。
没有对象:
class Cat(s: String)
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat("second cat") // error
现在有了对象:
class Cat(s: String)
object Cat {
def apply(s: String) = new Cat(s)
}
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat.apply("second cat") // OK
val myThirdCat: Cat = Cat("third cat") // OK (uses apply under the hood)
val myFourthCat: Cat = Cat { "fourth cat" } // OK as well
请注意第四次 cat 调用如何与花括号配合得很好,因为方法可以通过代码块传递(将传递代码块中最后计算的值,就像在函数中一样)。
3. 从某种意义上说,案例类是另一种稍微“特殊”的 Scala 构造,它们通过自动为您提供一些“幕后”内容(包括与 apply() 关联的伴随对象)来为您提供便利。
case class Cat(s: String)
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat.apply("second cat") // OK
val myThirdCat: Cat = Cat("third cat") // OK
在你的 Future 案例中发生的是数字 2,与“第四只猫”相同。关于您关于 new Cat(args)
等同于 Cat { args }
的问题,这很可能是第 3 种情况 - Cat
是一个案例类.无论是那个,还是它的伴随对象显式定义了 apply()
方法。
关于scala - scala中的对象实例化变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51555557/