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

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

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

相关文章
|
6月前
|
安全 Cloud Native Devops
【Aquasec翻译计划】微隔离:它的工作原理、类型、用例等
【Aquasec翻译计划】微隔离:它的工作原理、类型、用例等
308 2
|
15天前
|
Java Spring
玩转对象掌控权:深入Spring,精准控制对象创建次数
玩转对象掌控权:深入Spring,精准控制对象创建次数
18 0
|
8月前
|
Web App开发 机器人 数据安全/隐私保护
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
132 0
|
12月前
|
消息中间件 存储 运维
难住了,微服务之间的几种调用方式哪种最佳?
难住了,微服务之间的几种调用方式哪种最佳?
|
供应链 定位技术
验证限界上下文的原则
验证限界上下文的原则
验证限界上下文的原则
|
消息中间件 缓存 前端开发
DDD 实战 (4):战略设计之系统上下文和限界上下文
DDD 实战 (4):战略设计之系统上下文和限界上下文
DDD 实战 (4):战略设计之系统上下文和限界上下文
|
Scala 开发者
视图界定的介绍应用实例3 | 学习笔记
快速学习视图界定的介绍应用实例3
60 0
视图界定的介绍应用实例3 | 学习笔记
|
Scala 开发者
视图界定的介绍应用实例2 | 学习笔记
快速学习视图界定的介绍应用实例2
54 0
视图界定的介绍应用实例2 | 学习笔记
|
Scala 开发者
视图界定的介绍应用实例1 | 学习笔记
快速学习视图界定的介绍应用实例1
49 0
视图界定的介绍应用实例1 | 学习笔记
|
数据库连接 Python