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

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

开发者学堂课程【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上去了,编译器会做会做很多工作。

相关文章
|
5天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
|
4天前
|
云安全 人工智能 自然语言处理
阿里云x硅基流动:AI安全护栏助力构建可信模型生态
阿里云AI安全护栏:大模型的“智能过滤系统”。
|
4天前
|
人工智能 自然语言处理 自动驾驶
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
|
Linux 虚拟化 iOS开发
VMware Workstation Pro 25H2 for Windows & Linux - 领先的免费桌面虚拟化软件
VMware Workstation Pro 25H2 for Windows & Linux - 领先的免费桌面虚拟化软件
1021 0
|
7天前
|
存储 机器学习/深度学习 人工智能
大模型微调技术:LoRA原理与实践
本文深入解析大语言模型微调中的关键技术——低秩自适应(LoRA)。通过分析全参数微调的计算瓶颈,详细阐述LoRA的数学原理、实现机制和优势特点。文章包含完整的PyTorch实现代码、性能对比实验以及实际应用场景,为开发者提供高效微调大模型的实践指南。
647 2
|
6天前
|
JavaScript API 开发工具
如何在原生App中调用Uniapp的原生功能?
如何在原生App中调用Uniapp的原生功能?
318 139
|
5天前
|
编解码 自然语言处理 文字识别
Qwen3-VL再添丁!4B/8B Dense模型开源,更轻量,仍强大
凌晨,Qwen3-VL系列再添新成员——Dense架构的Qwen3-VL-8B、Qwen3-VL-4B 模型,本地部署友好,并完整保留了Qwen3-VL的全部表现,评测指标表现优秀。
438 7
Qwen3-VL再添丁!4B/8B Dense模型开源,更轻量,仍强大