隐式转换函数_隐函数可以转化为显函数

隐式转换函数_隐函数可以转化为显函数隐式转换函数是以implicit关键字声明的带有单个参数的函数。这种函数将会自动应用,将值从一种类型转换为另一种类型objectDemo1Main{defmain(args:Array[String]):Unit={valnum:Int=f1(3.5);valnum1:Int=3.5;print(num)}implic…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

隐式转换函数(implicit conversion function)是以implicit关键字声明的带有单个参数的函数,这样的函数将被自动应用,将值从一种类型转换为另一种类型。隐式转换函数叫什么名字是无所谓的,因为通常不会由用户手动调用,而是由Scala进行调用。但是如果要使用隐式转换,则需要对隐式转换函数进行导入。因此通常建议将隐式转换函数的名称命名为“one2one”的形式。
scala会考虑如下位置的隐式转换函数:

1、位于源或目标类型的伴生对象中的隐式函数

2、位于当前作用域可以以单个标识符指代的隐式函数

隐式转换在如下三种不同情况下会被考虑:

1、当表达式类型与预期类型不同时

2、当对象访问一个不存在成员时

3、当对象调用某个方法,而这个方法的参数声明与传入参数不匹配时

有三种情况编译器不会尝试使用隐式转换

1、如果代码能够在不使用隐式转换的前提下通过编译,则不会使用隐式转换

2、编译器不会尝试同事执行多个转换

3、存在二义性的转换是错误。

object Demo1Main { 
   
  def main(args: Array[String]): Unit = { 
   
    val num:Int = f1(3.5);
    val num1:Int = 3.5;
      print(num)
  }
  implicit def f1(d: Double): Int = { 
   d.toInt}

}

隐式转换的注意事项和细节

1、隐式转换函数的函数名可以是任意的,隐式转换与函数名称无关,只与函数签名(函数参数类型和返回值类型)有关。

2、隐式函数可以有多个(即:隐式函数列表),但是需要保证在当前环境下,只有一个隐式函数能被识别

隐式参数

定义
1、定义一个普通变量,使用 implicit 关键字修饰,定义一个函数调用这个变量当参数时,此时这个参数就被称为隐式参数
2、隐式参数的作用:减少提供函数参数的数量,让某些参数拥有隐藏的值(隐式变量)

def main(args: Array[String]): Unit = { 
   
   //隐式参数(每种类型只能有一个)
    implicit var a:Int = 10
    implicit var str:String = "hello"

    def fun(a:Int,b:Int)(implicit c:Int=5):Int={ 
   
      a+b+c
    }
    def fun2(a:Int,b:Int)(c:Int):Int={ 
   
      a+b+c
    }
    def fun3(a:Int,b:Int)(implicit c:Int=5,str:String):Int={ 
   
      println(str)
      a+b+c
    }
    //优先级:传参 > 隐式参数 > 默认
    println("fun结果:"+fun(10,10))   //30 调用隐式参数10 //25 默认赋值5
    println("fun结果:"+fun(10,10)(20)) //40 传参20
    println("fun2结果:"+fun2(10,10)(20))
    println("fun3结果:"+fun3(10,10))
    println("fun3结果:"+fun3(10,10)(20,"heheda"))
}

隐式类

基本介绍

在scala2.10后提供了隐式类,可以使用implicit声明类,隐式类的非常强大,同样可以扩展类的功能,比前面使用隐式转换丰富类库功能更加的方便,在集合中隐式类会发挥重要的作用。

隐式类使用有如下几个特点:

其所带的构造参数有且只能有一个
隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是 顶级的(top-level objects)。
隐式类不能是case class(case class在后续介绍 样例类)
作用域内不能有与之相同名称的标识符

package com.liu.yinshi

object Demo2Main { 
   

  def main(args: Array[String]): Unit = { 
   
    implicit class DB1(val mysql: Mysql) { 
   
      def addSufix(): String = { 
   
        mysql.driver + " scala"
      }
    }
    val mysql = new Mysql;
    val str = mysql.addSufix()
    println(str)

  }
}



package com.liu.yinshi

class Mysql { 
   
  val driver = "mysqlDriver"

  def insert(): Unit ={ 
   
    print("insert function")
  }

  def sayOk(): Unit ={ 
   
    println("sayOk")
  }
}

转换时机

当方法中的参数的类型与目标类型不一致时
当对象调用所在类中不存在的方法或成员时,编译器会自动将对象进行隐式转换(根据类型)

隐式解析机制

即编译器是如何查找到缺失信息的,解析具有以下两种规则:
首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象)。(一般是这种情况)
如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。类型的作用域是指与该类型相关联的全部伴生模块,一个隐式实体的类型T它的查找范围如下(第二种情况范围广且复杂在使用时,应当尽量避免出现):
a) 如果T被定义为T with A with B with C,那么A,B,C都是T的部分,在T的隐式解析过程中,它们的伴生对象都会被搜索。
b) 如果T是参数化类型,那么类型参数和与类型参数相关联的部分都算作T的部分,比如List[String]的隐式搜索会搜索List的伴生对象和String的伴生对象。
c) 如果T是一个单例类型p.T,即T是属于某个p对象内,那么这个p对象也会被搜索。
d) 如果T是个类型注入S#T,那么S和T都会被搜索。

隐式转换的前提

在进行隐式转换时,需要遵守两个基本的前提:

不能存在二义性
隐式操作不能嵌套使用 // [举例:]如:隐式转换函数

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/183907.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • c#/winform中InitializeComponent()函数的作用[通俗易懂]

    InitializeComponent()方法写在前面和后面是有区别的。InitializeComponent()方法是用来初始化窗体组件的,在InitializeComponent之前,窗体的各个控件还没有进行初始化,比如说窗体上有一个TextBoxUserName,在InitializeComponent之前它还只是一个TextBox类型的变量而已,如果在InitializeComponent之前调用这个TextBox的属性或方法,就会出错。再比如说你拖上取一个TextBox,它放在Form的位置,Te

    2022年4月14日
    67
  • 宝塔面板无法卸载php,宝塔面板如何卸载「建议收藏」

    宝塔面板无法卸载php,宝塔面板如何卸载「建议收藏」windows面板卸载1.打开宝塔面板windows版安装目录,路径为:面板安装数据盘:\BtSoft\ServerAdmin2.运行UnInstall.exe开始面板卸载3.最后使用注册表清理软件或者360清理,清理注册表才可以清除服务文件。在卸载完成后,重启服务器以确保卸载干净。linux面板卸载方法一、脚本卸载1.你需要先在面板中将通过面板安装的所有软件卸载,如nginx、mysql、…

    2022年9月6日
    3
  • Q学习(Q-learning)简单理解「建议收藏」

    Q学习(Q-learning)简单理解「建议收藏」第1节Q-learning逐步教程本教程将通过一个简单但又综合全面的例子来介绍Q-learning算法。该例子描述了一个利用无监督训练来学习未知环境的agent。假设一幢建筑里面有5个房间,房间之间通过门相连。我们将这五个房间按照从0至4进行编号,且建筑的外围可认为是一个大的房间,编号为5。房间结构如下图:上图的房间也可以通过一个图来表示,房间作为图的节点,两个房间若有门相连,则相应节点间对应一条边如图2所示图2房间结构对应的图第2节Q-learning手工推演…

    2022年10月3日
    0
  • 重写和重载的区别是什么「建议收藏」

    重写和重载的区别是什么「建议收藏」重写和重载的区别是什么

    2022年9月8日
    0
  • vue-router中的beforeEach

    vue-router中的beforeEach最近在做vue项目的开发,用到的技术栈主要是vue相关的,在开发这个项目的时候,设计到了权限,因为是后台管理系统,不同的身份和角色访问系统的时候,系统所展现出来的可访问内容都是不一样的,有兴趣的同学可以参考下RBAC(以角色为基础的权限管理设计)这篇文章写得很详细,很直观,我写这篇文章主要是想要分享一下前端的技术栈vue-router是如何处理的,以及踩过的坑。vue-router可以参考官方文档vue-router,官方文档中介绍的很详细,解决权限问题,就用到了addRoutes这个API,去动态添

    2022年6月28日
    31
  • 前端学到什么程度可以找到工作(应届毕业生有什么优势)

    目录1.前端开发下载安装VScode优化配置2、插件安装3、设置字体大小4、开启完整的Emmet语法支持5、视图2.Node.js入门2.1、什么是Node.js2.2、Node.js有什么用2.3、安装下载:2.4、快速入门2.5、服务器端应用开发3、ES6入门3.2、let声明变量3.3、const声明常量3.4、解构赋值创建3.5、模板字符串创建3.6、声明对象简写创建3.7、定义方法简写3.8、对象拓展

    2022年4月16日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号