微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Scala 中的装饰者模式

如何解决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)

不,Decoratorinfo类型

info 被声明为一个从 LoggerLoggerDecorator 扩展为)的函数。

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 不需要 Decoratoruppercase is Decorator,这意味着它是一个带有 {{1} } 并返回一个 Logger

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

我尝试传递这样的命名参数 Logger 我收到一个错误。

在这种情况下,println(x) 是什么?

您需要创建一个 x,意思是一个接受字符串且不返回任何特殊内容的函数。

Logger 可以。

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

println(_)println(somethingElse) 不再是接受字符串的函数(它们不再接受任何参数),因此它们不是 println(123)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。