首页 > 解决方案 > Scala 中的隐式函数。这是如何工作的?

问题描述

我正在关注 Scala 中的教程,我看到了这一点:

object implicitFunctions extends App {
    println("Step 1: How to create a wrapper String class which will extend the String type")
    class DonutString(s: String) {
        def isFavoriteDonut: Boolean = s == "Glazed Donut"
    }

    println("\nStep 2: How to create an implicit function to convert a String to the wrapper String class")
    object DonutConversions {
        implicit def stringToDonutString(s: String) = new DonutString(s)
    }

    println("\nStep 3: How to import the String conversion so that it is in scope")
    import DonutConversions._

    println("\nStep 4: How to create String values")
    val glazedDonut = "Glazed Donut"
    val vanillaDonut = "Vanilla Donut"

    println("\nStep 5: How to access the custom String function called isFavaoriteDonut")
    println(s"Is Glazed Donut my favorite Donut = ${glazedDonut.isFavoriteDonut}")
    println(s"Is Vanilla Donut my favorite Donut = ${vanillaDonut.isFavoriteDonut}")
}

究竟发生了什么?我想在类上没有找到方法String,所以我们查看导入的隐式并通过调用函数并传入丢失方法的接收者(字符串)来进行String转换stringToDonutString。那正确吗?

为什么隐式必须包装在对象中?

标签: scala

解决方案


 ${glazedDonut.isFavoriteDonut}"

调用上述方法时,编译器会在 String 中搜索isFavoriteDonut方法(因为glazedDonut是 String 类型)。当然,它没有找到它。

所以编译器,然后搜索一个隐式的,它可以转换String为其他类型(让我们称之为Unknown),这样这个Unknown类型就包含isFavoriteDonut方法。

它在作用域中找到了这样一个隐式函数,它可以转换String => DonutString并且它知道DonutString包含glazedDonut

为什么隐式必须包装在对象中?

该规范不允许创建顶级implicit类和函数。https://scala-lang.org/files/archive/spec/2.12/07-implicits.html

对于所有类型成员以及顶级对象,隐式修饰符都是非法的。


推荐阅读