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

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

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

相关文章
|
安全 Cloud Native Devops
【Aquasec翻译计划】微隔离:它的工作原理、类型、用例等
【Aquasec翻译计划】微隔离:它的工作原理、类型、用例等
471 2
|
4月前
|
SQL 开发者
访问者模式问题之FunctionExtractor是怎么工作的,以从SqlNode中提取函数名称的
访问者模式问题之FunctionExtractor是怎么工作的,以从SqlNode中提取函数名称的
|
4月前
|
机器学习/深度学习 自然语言处理
上下文无关与上下文相关
上下文无关与上下文相关
|
5月前
|
容器
通用研发提效问题之区分女娲上下文中的共享字典和隔离字典,如何解决
通用研发提效问题之区分女娲上下文中的共享字典和隔离字典,如何解决
|
6月前
|
XML 搜索推荐 数据格式
资源描述框架的用途及实际应用解析
**RDF(资源描述框架)**是一种用于机器理解网络资源的框架,使用XML编写。它通过URI标识资源,用属性描述资源,便于计算机应用程序处理信息。RDF在语义网上促进信息的确切含义和自动处理,使得网络信息可被整合。RDF语句由资源、属性和属性值组成。RDF文档包括`<rdf:RDF>`根元素和`<rdf:Description>`元素,后者用`about`属性标识资源。RDF还支持容器(如`<Bag>`、`<Seq>`和`<Alt>`)来描述集合。RDFS是RDF的扩展,提供描述类和属性的框架,而达布林核心是一组预定义属性,用于描述文
191 0
|
Web App开发 机器人 数据安全/隐私保护
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
177 0
|
消息中间件 缓存 前端开发
DDD 实战 (4):战略设计之系统上下文和限界上下文
DDD 实战 (4):战略设计之系统上下文和限界上下文
DDD 实战 (4):战略设计之系统上下文和限界上下文
|
供应链 定位技术
验证限界上下文的原则
验证限界上下文的原则
验证限界上下文的原则
|
Scala 开发者
视图界定的介绍应用实例3 | 学习笔记
快速学习视图界定的介绍应用实例3
视图界定的介绍应用实例3 | 学习笔记
|
Scala 开发者
视图界定的介绍应用实例1 | 学习笔记
快速学习视图界定的介绍应用实例1
视图界定的介绍应用实例1 | 学习笔记