上下文界定介绍和应用实例 | 学习笔记

简介: 快速学习上下文界定介绍和应用实例

开发者学堂课程【Scala 核心编程 - 进阶上下文界定介绍和应用实例学习笔记,与课程紧密连接,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/610/detail/9158


上下文界定介绍和应用实例


内容介绍

一、基本介绍

二、上下文界定应用实例


一.基本介绍

与 view bounds 一样 context bounds(上下文界定)也是隐式参数的语法糖。为语法上的方便,引入了"上下文界定”这个概念


二.上下文界定应用实例

要求:使用上下文界定+隐式参数的方式,比较两个Person对象的年龄大小

要求:使用 Ordering 实现比较

ordered 和 ordering 区别:

ordered 是实现继承的一个接口。往往是去重写,或者是实现它的compare方法;

ordering是以继承的方式去写comparator,comparator是个比较器,是通过写外置的对象去实现这个方法。

object ContextBoundsDemo{

implicit val personComparetor=new Ordering Person] {

override def compare(p1:Person,p2:Person):Int=

p1.age-p2.age

}

def main(args:Array[String):Unit={

val p1=new Person(“mary“,30)

val p2=new Person(“smith”,35)val compareComm4=new CompareComm4(p1p2) printin(compareComm4geatter)val compareComm5=newCompareComm5(p1p2) printin(compareComm5.geatter)val compareComm6=new CompareComm6(p1p2) printin(compareComm6.geatter)

//方式1

class CompareComm4[T: Ordering](obj1:T,obj2:T)(implicit comparetor: Ordering[T]){

def geatter=if (comparetor.compare(obj1,obj2)>0)obj1 elseobj2

}

//方式2,将隐式参数放到方法内

class CompareComm5T:Ordering](o1: To2:T){

def geatter={

def f1(implicit cmptor:Ordering[T])=cmptor.compare(o1.o2)

if (f1 > 0) o1 else o2

}}

//方式3,使用implicitly语法糖,最简单(推荐使用)

class CompareComm6T:Orderingl(o1:To2:T{

def geatter={

//这句话就是会发生隐式转换,获取到隐式值personComparetor val comparetor=implicitly[Ordering[T]]

printin"CompareComm6comparetor"+comparetor.hashCode())

if(comparetor.compare(o1,o2)>0)o1 else o2

}}

//一个普通的Person类

class Person(val name: String,val age:Int){

override def toString=this.name +"\t"+ this.age

}

image.png新建一个包:

在里面建一个文件:

image.png

package com.atguigu.chapter18.contextbounds

object contextBoundsDemo {

//这里我定义一个隐式值 Ordering [Person]

implicit val personComparetor=new Ordering [Person4] {

override def compare(p1:Person4,p2:Person4):Int=

p1.age-p2.age

}

def main(args: Array[String]): Unit = {

val p1=new Person4(“mary“,30)

val p2=new Person4(“smith”,35)val compareComm4=new CompareComm4(p1p2) printin(compareComm4geatter)// “smith”,35

//传进去的时候比较器也会被找到,如何知道传进去类型是实现ordering呢?

因为隐式值这个参数里面知道ordering,所以才能用。这时再执行一定会返回斯密斯这个信息。

val compareComm5=new CompareComm5(p1,p2) println(compareComm5.geatter) // "smith", 35

}

}

//一个普通的Person类

class Person4(val name: String, val age: Int) {

//重写toStirng

override def tostring = this.name + "\t"+ this.age

}

//方式1

//说明:

//1.[T:Ordering] 泛型

//2.obj1:T,obj2:T 接受T类型的对象

//3. implicit comparetor: Ordering[t] 是一个隐式参数

class CompareComm4[T: Ordering](obj1:T,obj2:T)(implicit comparetor: Ordering[T]){

def geatter=if (comparetor.compare(obj1,obj2)>0)obj1 elseobj2

}

回忆一下隐式值和隐式参数的定义:

implicit val str1: String ="jack~" //这个就是隐式值

//implicit name: String:name就是隐式参数

如果什么都没有传,那么编译器会在底层直接将隐式值装进去。

其实上面就使用到了隐式值和隐式参数的方法,只是上面的更复杂一点。

下面执行一下:

image.png

//方式2,将隐式参数放到方法内

class CompareComm5T:Ordering](o1: To2:T){

def geatter={

def f1(implicit cmptor:Ordering[T])=cmptor.compare(o1.o2) //返回一个数字

//如果f1返回的值>0,就返回o1,否则返回o2

if (f1 > 0) o1 else o2

}

}

这种写法大家要看懂,当你觉得好像很奇怪的时候,只要看到这个东西,一定在上下文能够找到一个隐式值,只是这个隐式值,有可能是直接写在这里,也可能是引进来的,比如在这儿没有写而是用import引进来也是有可能的。这样的写法代码很简单。

下面执行代码:

val compareComm5=new CompareComm5(p1,p2) println(compareComm5.geatter) // "smith", 35

image.png

和我们想的是一样的。

//方式3,使用 implicitly 语法糖,最简单(推荐使用)

class CompareComm6T:Orderingl(o1:To2:T{

def geatter={

//这句话就是会发生隐式转换,获取到隐式值personComparetor

//底层仍然使用编译器来完成(绑定赋值)的工作

val comparetor=implicitly[Ordering[T]]

if(comparetor.compare(o1,o2)>0)o1 else o2

}}

运行以下代码:

val compareComm6=new CompareComm6(p1,p2) println(compareComm6.geatter) // "smith", 35

得到:

image.png

通过隐式转换拿到的比较器的地址是1018547642。现在要证明它和comparetor是同一个比较器:

直接在主函数里打:println("personComparetor hashcode=" + personComparetor.hashcode())

val compareComm6=new CompareComm6(p1,p2) println(compareComm6.geatter) // "smith", 35

compare 里也有一个用语法糖得到的hashcode。

点击运行:

image.png

运行之后可以看到这两个地址是完全一样的。外面的hashcode和得到的hashcode是同一个。其实就是语法糖的作用,它就相当于做一个转换。

有兴趣可以追究一下implicitly的源代码。它的底层是怎么做的呢? personComparetor有一个隐式值过后,在编译的时候直接就把比较器绑定到comparetor上去了,编译器会做会做很多工作。

相关文章
|
10月前
|
人工智能 算法 Serverless
短视频创作助手 | AI剧本生成与动画创作
短视频行业的快速发展得益于移动互联网和智能手机的普及,4G、5G网络的推广使用户对视频内容的需求大增。短视频以其短小精悍、易于传播的特点迅速吸引了大量用户。平台如抖音、快手通过算法推荐和社交功能推动了用户增长和内容生态繁荣。AI剧本生成与动画创作方案则进一步降低了创作门槛,简化从剧本到视频成片的过程。该方案利用阿里云的大模型服务平台百炼、函数计算FC和对象存储OSS等产品,实现了自动化流程,涵盖故事剧本撰写、插图设计、声音合成至视频合成,极大缩短了创作周期,提高了内容产出速度。部署简单快捷,耗时约5分钟,使得非技术人员也能轻松上手,满足企业和个人创作者的需求。
|
9月前
|
数据采集 Web App开发 API
B站高清视频爬取:Python爬虫技术详解
B站高清视频爬取:Python爬虫技术详解
|
9月前
|
SQL 监控 数据库
如何解决 SQL Server 占用内存过多问题
SQL Server 占用过多内存会导致响应缓慢和查询性能低下。解决流程包括:1) 查看内存使用情况,2) 分析各数据库内存占用,3) 优化 SQL Server 配置(如限制最大内存),4) 优化查询(如创建索引),5) 持续监控效果。通过这些步骤可有效控制内存占用,提升系统性能。
1164 0
|
移动开发 JavaScript 定位技术
百度地图开发:地图调起API(Web端)使用终点经纬度直接调用百度地图导航信息的解决方案
百度地图开发:地图调起API(Web端)使用终点经纬度直接调用百度地图导航信息的解决方案
786 0
|
JavaScript
基于Vue2.X对WangEditor 5富文本编辑器进行封装与使用,支持单个或多个图片点击、粘贴、拖拽上传,Vue3.X项目也可直接使用
这篇文章介绍了如何在Vue 2.X项目中封装和使用WangEditor 5富文本编辑器,支持图片的点击、粘贴和拖拽上传,同时提到封装的组件也适用于Vue 3.X项目,并提供了详细的使用示例和后端配置。
1807 1
基于Vue2.X对WangEditor 5富文本编辑器进行封装与使用,支持单个或多个图片点击、粘贴、拖拽上传,Vue3.X项目也可直接使用
|
Docker Windows 容器
Windows Docker Desktop 无法启动 自动退出报错信息为:Docker Desktop -Unexpected WsL error An unexpected error was e
Windows Docker Desktop 无法启动 自动退出报错信息为:Docker Desktop -Unexpected WsL error An unexpected error was e
1099 0
|
编解码 程序员 数据安全/隐私保护
没错,我是高端吃瓜玩家(搞懂摩斯密码)
在电气时代刚流行的时代,并没有电话手机,人们探索的第一步是如何用电去传讯消息,在这期间摩尔斯发明了电报并且获得了专利,并且他的团队(有说是他的助手艾尔菲德·维尔发明的摩尔斯电码)配套发明了一套传输的规则被称为摩尔斯电码。
1787 0
没错,我是高端吃瓜玩家(搞懂摩斯密码)
|
程序员 API C语言
【c/c++】属于程序员的浪漫,基于easyx.h图形库实现3D Heart
【c/c++】属于程序员的浪漫,基于easyx.h图形库实现3D Heart
438 0
|
运维 NoSQL
Cassandra 数据一致性修复 repair 来龙去脉
文章分3块:1.为什么需要repair?;2.repair大概流程?;3.repair可能的问题。
4015 0
Cassandra 数据一致性修复 repair 来龙去脉
|
物联网 Linux API
玩 High API 系列之:快速实现身份验证
很多APP都需要具备一个基本功能,就是对用户身份进行验证,例如对用户和身份证信息和银行卡信息进行校验。对于中小企业而言,且不说相关软件开发的巨大工作量,身份证和银行卡数据的获取就是很大的一个问题。中小企业可能需要小半年时间才能完成这个身份验证的功能。
3979 0