Scala中的装饰者模式

我在 Scala 中有以下代码。我有几个关于功能和语法的问题。

type Logger = String => Unit

type Decorator = Logger => Logger

  val uppercase: Decorator = 
    logger =>
      (msg: String) => logger(msg.toUpperCase)

  val info: Decorator =
    logger =>
      (msg:String) => logger("info " + msg)

我理解正确吗,那Decoratorìnfo函数的输入?

为什么这里不需要声明返回类型?

然后我使用这样的代码:

val prefixUppercase = info(uppercase(println(_)))

为什么我可以通过println(_)uppercase

uppercase函数需要一个类型为 的参数Decorator,这println()显然不是。

另外,我使用println(_),但是当我尝试传递这样的命名参数时,println(x)我收到一个错误。

回答

我理解正确吗,那Decoratorìnfo函数的输入?

val info: Decorator =
  logger =>
    (msg:String) => logger("info " + msg)

不,Decorator类型info

info被声明为一个函数 from Loggerto LoggerDecorator扩展到)。

val info: Decorator =  // info is a Decorator
                       // i.e. a function Logger => Logger

  logger =>            // so this makes logger a Logger
                       // (the input for the Decorator)

                       // what follows is the output of the Decorator
                       // i.e. another Logger
                       // i.e. a function String => Unit

    (msg:String) =>    // so this is that String input to the
                       // resulting (decorated) Logger  


       logger("info " + msg)  // and this is what our decorator does
                              // to the String to be logged:
                              // we prefix it with "info "
                              // and give it to the underlying logger

为什么这里不需要声明返回类型?

正在声明返回类型(见上文)。

一般来说,Scala 非常擅长推断类型,因此您实际上不需要声明类型info是否可以从其他已知类型派生,但是

a) 声明非显而易见的类型是一种很好的做法,尤其是在公共值上。这可以作为文档,加速编译并可以避免错误(如果推断的类型不是你想要的,它有助于追踪问题)

b) 在你的情况下,这也是让编译器知道logger这里应该有什么类型的最直接的方法。否则,您将不得不在其他地方声明。

为什么我可以通过println(_)uppercase?大写函数需要一个类型为 的参数Decorator,这println()显然不是。

uppercase不需要 a Decoratoruppercase a Decorator,这意味着它是一个接受 aLogger并返回 a的函数Logger

所以它需要 a Logger,这是一个接受 aString并且不返回任何内容的函数。println是这样一个函数,因此您可以将其传递给uppercase(作为其Logger输入参数)。

我尝试传递这样的命名参数println(x),但出现错误。

什么是x在这种情况下?

您需要创建一个Logger,这意味着一个接受 String 并且不返回任何特殊内容的函数。

x => println(x) 会做。

println(_) 是同一件事的简写,并且会做。

println(somethingElse)或者println(123)不再接受 String 的函数(它们不再接受任何参数)所以那些不是Loggers。


以上是Scala中的装饰者模式的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>