由于 Scala 的一致性,编写返回函数的方法与您在前面部分中看到的所有内容类似。例如,假设您想编写一个返回函数的 greet
方法。我们再次从问题陈述开始
我想创建一个返回函数的
greet
方法。该函数将采用一个字符串参数,并使用println
打印它。为了简化此第一个示例,greet
不会采用任何输入参数;它只会构建一个函数并返回它。
给定该陈述,您可以开始构建 greet
。您知道它将是一个方法
def greet()
您还知道此方法将返回一个函数,该函数 (a) 采用 String
参数,并且 (b) 使用 println
打印该字符串。因此该函数的类型为 String => Unit
def greet(): String => Unit = ???
----------------
现在您只需要一个方法体。您知道该方法需要返回一个函数,并且该函数采用 String
并打印它。此匿名函数符合该描述
(name: String) => println(s"Hello, $name")
现在您只需从方法中返回该函数
// a method that returns a function
def greet(): String => Unit =
(name: String) => println(s"Hello, $name")
由于此方法返回一个函数,因此您可以通过调用 greet()
来获取该函数。这是在 REPL 中执行的一个好步骤,因为它验证了新函数的类型
scala> val greetFunction = greet()
val greetFunction: String => Unit = Lambda....
-----------------------------
现在您可以调用 greetFunction
greetFunction("Joe") // prints "Hello, Joe"
恭喜,您刚刚创建了一个返回函数的方法,然后执行了该函数。
改进方法
如果您能够传递问候语,我们的方法会更有用,所以让我们这样做。您所要做的就是将问候语作为参数传递给 greet
方法,并在 println
内部的字符串中使用它
def greet(theGreeting: String): String => Unit =
(name: String) => println(s"$theGreeting, $name")
现在,当您调用方法时,该过程会更灵活,因为您可以更改问候语。当您从此方法创建函数时,它看起来像这样
scala> val sayHello = greet("Hello")
val sayHello: String => Unit = Lambda.....
------------------------
REPL 类型签名输出显示 sayHello
是一个函数,它采用 String
输入参数并返回 Unit
(无)。因此,现在当您向 sayHello
提供 String
时,它会打印问候语
sayHello("Joe") // prints "Hello, Joe"
您还可以根据需要更改问候语以创建新函数
val sayCiao = greet("Ciao")
val sayHola = greet("Hola")
sayCiao("Isabella") // prints "Ciao, Isabella"
sayHola("Carlos") // prints "Hola, Carlos"
一个更贴近现实的示例
当您的方法返回许多可能函数中的一个时,此技术会更有用,例如返回自定义函数的工厂。
例如,假设您想编写一个返回以不同语言向人们问候的函数的方法。我们将此限制为根据传递给方法的参数以英语或法语问候的函数。
您知道的第一件事是您要创建一个方法,该方法 (a) 采用“所需语言”作为输入,并且 (b) 返回一个函数作为其结果。此外,由于该函数打印给定的字符串,因此您知道它的类型为 String => Unit
。有了这些信息,您可以编写方法签名
def createGreetingFunction(desiredLanguage: String): String => Unit = ???
接下来,因为您知道您将返回的可能函数采用一个字符串并打印它,所以您可以为英语和法语编写两个匿名函数
(name: String) => println(s"Hello, $name")
(name: String) => println(s"Bonjour, $name")
在方法内部,如果您给这些匿名函数一些名称,可能会更具可读性,所以让我们将它们分配给两个变量
val englishGreeting = (name: String) => println(s"Hello, $name")
val frenchGreeting = (name: String) => println(s"Bonjour, $name")
现在您需要做的就是 (a) 如果 desiredLanguage
为英语,则返回 englishGreeting
,并且 (b) 如果 desiredLanguage
为法语,则返回 frenchGreeting
。一种方法是使用 match
表达式
def createGreetingFunction(desiredLanguage: String): String => Unit = {
val englishGreeting = (name: String) => println(s"Hello, $name")
val frenchGreeting = (name: String) => println(s"Bonjour, $name")
desiredLanguage match {
case "english" => englishGreeting
case "french" => frenchGreeting
}
}
def createGreetingFunction(desiredLanguage: String): String => Unit =
val englishGreeting = (name: String) => println(s"Hello, $name")
val frenchGreeting = (name: String) => println(s"Bonjour, $name")
desiredLanguage match
case "english" => englishGreeting
case "french" => frenchGreeting
而这就是最终方法。请注意,从方法返回函数值与返回字符串或整数值没有区别。
这是 createGreetingFunction
构建法语问候函数的方式
val greetInFrench = createGreetingFunction("french")
greetInFrench("Jonathan") // prints "Bonjour, Jonathan"
而这是它构建英语问候函数的方式
val greetInEnglish = createGreetingFunction("english")
greetInEnglish("Joe") // prints "Hello, Joe"
如果您对该代码感到满意,那么恭喜您,您现在知道如何编写返回函数的方法。