柯里化详解
语法 : 函数有多个参数列表
意义: 方便数据的演变, 后面的参数可以借助前面的参数推演 , foldLeft的实现
有多个参数列表 的函数就是柯里化函数,所谓的参数列表就是使用小括号括起来的函数参数列表
curry化最大的意义在于把多个参数的function等价转化成多个单参数function的级联,这样所有的函数就都统一了,方便做lambda演算。 在scala里,curry化对类型推演也有帮助,scala的类型推演是局部的,在同一个参数列表中后面的参数不能借助前面的参数类型进行推演,curry化以后,放在两个参数列表里,后面一个参数列表里的参数可以借助前面一个参数列表里的参数类型进行推演。这就是为什么 foldLeft这种函数的定义都是curry的形式
使用implicit 修饰的内容是隐式内容, 隐式的特点就是遇到适应的类型会自动的应用
意义:
使得静态类型动态化
为现有类库添加功能
隐式的代理增强一个类或者一个方法
分类:
隐式参数
隐式函数
隐式类
隐式变量
定义隐式变量
object MyValue {
implicit val age:Int = 19
implicit val name:String = "lisi"
}
定义隐式变量
/** * 这个方法的所有的参数是隐式参数 * 可以使用柯里化来定义个别的隐式参数 * add(x:Int)(implicit y:Int , z:Int) * 上面的例子中x为正常参数 y z都为隐式参数 * @param name * @param age */
def myShow(implicit name: String, age: Int): Unit = {
println(name + " " + age)
}
演示现象
def main(args: Array[String]): Unit = {
new Show().myShow("reba",12)
// 导入了隐式参数 就会从context中寻找隐式数据
// context中只能有一个匹配类型的数据
// 如果找到多个匹配类型的数据就会报错
import MyValue._
//lisi 19
new Show().myShow
}
应用示例
class A[T] {
def mymax1(x:T ,y:T): T ={
if(x > y) x else y// T类型中没有定义>方法 报错
}
// T类型必须是可以隐式的转换成Ordered的类型 , 这个隐式转换要事先定义
def mymax2(x:T ,y:T)(implicit order:T=>Ordered[T]): T ={
if(x > y) x else y
}
}
object A{
def main(args: Array[String]): Unit = {
// Int已经默认的实现了 Orderd的实时转换
val res: Int = new A[Int]().mymax2(12,34)
println(res)
}
}
隐式函数
函数处理的数据类型 => 返回的数据类型 , 当遇到对应的类型=>类型处理的时候隐式函数会自动的应用
增强一个类
添加不存在的函数,implicit作用于函数,称之为隐式函数
定义一个类只有add的方法
* 2019/11/12
* 定义一个类 类中定义一个方法
*
* @author Hangge.z WX:17710299606
* 想对类增强一些方法
*
*/
class Demo {
val add = (x: Int, y: Int) => {
x + y
}
}
定义一个增强的类
/** * 增强类 * 定义一个减法方法 * @param demo */
class Advice(val demo: Demo) {
val substract = (x: Int, y: Int) => {
x - y
}
}
编写一个隐式转换的方法类
/** * 将Demo类隐式转换成增强的类 这样我们被增强的类既有自己的方法也有增强类的方法 这样就实现的了隐式函数对一个类增强的目的 */
object ImplicitAdvice {
//将Demo类隐式转换成增强类 实现对Demo类增强的目的
implicit def advice(demo: Demo) = {
new Advice(demo)
}
}
演示
object Test2 {
def main(args: Array[String]): Unit = {
val demo = new Demo
//在这里调用没有substract方法
val sum: Int = demo.add(1,2)
import ImplicitAdvice._
val res2: Int = demo.substract(33,20)
println(sum)
println(res2)
}
}
隐式类
增强一个类型
隐式类约束
隐式类必须有一个带一个参数的主构造函数
必须定义在另一个class/object/trait里面(不能独立定义)
隐式类构造器只能带一个不是implicit修饰的参数
作用域中不能有与隐式类类型相同的成员变量,函数以及object名称
定义一个类
class B {
val add = (x: Int, y: Int) => {
x + y
}
}
定义一个隐式类
/** * 隐式主题类 */
object ImplicitContext{
//隐式类只能对一种类型的类进行增强 B类或者子类增强
implicit class RichB(b:B){
def multiply(x: Int, y: Int) = {
x * y
}
}
}
演示增强效果
def main(args: Array[String]): Unit = {
val b = new B // B类 以及他的子类
println(b.add(12, 12))
import ImplicitContext._
println(b.multiply(12, 12))
}
注意
如果代码无需隐式转换即可通过编译,则不会引入隐式转换
隐式转换只会匹配一次,即隐式转换至多发生一次
存在二义性的隐式转换报错,
泛型详解
泛型类似于java中的泛型 ,泛型可以定义在类上 ,方法上和属性上 ,用于约束类型 !
如果我们要求函数的参数可以接受任意类型。也可以使用泛型,这个类型可以代表任意的数据类型。
泛型类
/** * 2019/11/12 * 泛型类 * 将泛型定义在类型上 * @author Hangge.z WX:17710299606 * */
class GenericClass[K,V](k:K,v:V) {
def show(): Unit ={
println(k+"----->"+v)
}
}
object Test1{
def main(args: Array[String]): Unit = {
// 不需要指定类型 自动推断
val gc = new GenericClass("Jack",999.99)
// 指定类型
val gc1 = new GenericClass[String , String]("jim", "cat")
// 指定类型 , 如果传入的数据怒符合类型会报错
val gc2 = new GenericClass[String , Int]("jim", "cat")
gc.show()
}
}
泛型方法
/** * 2019/11/12 * 泛型方法 * 将泛型定义在方法上 * @author Hangge.z WX:17710299606 * */
class GenericFunction {
// 定义一个泛型方法 参数和返回值都是泛型
def show[T](x: T): T = {
x
}
}
object GenericFunction {
def main(args: Array[String]): Unit = {
val gf = new GenericFunction
// 不指定类型 自动推断
println(gf.show("hello"))
println(gf.show(23))
println(gf.show(99.99))
// 指定函数传入的类型
println(gf.show[Int](12))
}
}
上界
有时,需要明确指定范型类T是某个类或者Trait的子类型,比如Comparable接口的子类,这样,才能对泛型类对象进行比较操作。Comparable是泛型的上界!
在 Java 泛型里表示某个类型是 A 类型的子类型,使用 extends 关键字,这种形式叫 upper bounds(上限或上界),
<T extends A>
//或用通配符的形式:
<? extends A>
在 scala 里表示某个类型是 A 类型的子类型,也称上界或上限,使用 <: 关键字,语法如下:
[T <: A]
//或用通配符:
[_ <: A]
/** * 2019/11/12 * 定义一个继承了Ordered的类传入上界泛型中去 * @author Hangge.z WX:17710299606 * */
class User(var name:String , var age:Int) extends Ordered[User]{
override def compare(that: User): Int = {
this.age-that.age
}
}
/** * 2019/11/12 * 上界 传入的参数必须是定义的Ordered 的子类 否则在运行的时候会报错 * @author Hangge.z WX:17710299606 * */
class UpperDemo[T <: Ordered[T]](v1:T , v2:T) {
def max(): T ={
if (v1>v2) v1 else v2
}
}
object TestT{
def main(args: Array[String]): Unit = {
val ut = new UpperDemo(new User("a",32),new User("a",23))
println(ut.max().age)
}
}
下界
要求: 传入的类型或者处理的类型是某种类型的父类
在 Java 泛型里表示某个类型是 A类型的父类型,使用 super 关键字
<T super A>
//或用通配符的形式:
<? super A>
scala中下界
在 scala 的下界或下限,使用 >: 关键字,语法如下:
[T >: A]
//或用通配符:
[_ >: A]
/** * 2019/11/12 * 下界 必须是A的父类 * @author Hangge.z WX:17710299606 * */
class A extends B
class B {
}
class C
//泛型中的T的类型必须是A的父类 或者A类型 下界
class LowDemo[T >: A]{
def test(x:T)={
println(x)
}
}
object LowDemo{
def main(args: Array[String]): Unit = {
// 泛型中执行传入A的父类以及本身
val ld = new LowDemo[A]
println(ld)
}
}
上下文界定
在隐式参数详解的时候 ,需要一个隐式参数来将泛型中的类型隐式转换成对应的类型
视图界定
<% 的意思是“view bounds”(视界),它比<:适用的范围更广,除了所有的子类型,还允许隐式转换类型。
目的是为了省略隐式值的书写
// 视图界定 存在一个隐式转换 直接将泛型T转成Ordered的子类
def max[T <% Ordered[T]](x:T , y:T): T ={
if(x>y) x else y
}
def main(args: Array[String]): Unit = {
val res: User = max(new User("", 23) , new User("",34))
println(res)
}
逆变和协变
1.泛型集合都是协变的,对于List而言,如果B是A的子类,那么List[B]也是List[A]的子类,即可以把List[B]的实例赋值给List[A]变量
2.Scala的协变(+),逆变(-),协变covariant、逆变contravariant、不可变invariant
3.对于一个带类型参数的类型,比如 List[T],如果对A及其子类型B,满足 List[B]也符合List[A]的子类型,那么就称为covariance(协变) ,如果 List[A]是 List[B]的子类型,即与原来的父子关系正相反,则称为contravariance(逆变)。如果一个类型支持协变或逆变,则称这个类型为variance(翻译为可变的或变型),否则称为invariance(不可变的)
4.在Java里,泛型类型都是invariant,比如 List 并不是 List 的子类型。而scala支持,可以在定义类型时声明(用加号表示为协变,减号表示逆变)
5.如: trait List[+T] // 在类型定义时声明为协变这样会把List[String]作为List[Any]的子类型。
里引入关于这个符号的说明,在声明Scala的泛型类型时,“+”表示协变,而“-”表示逆变
C[+T]:如果A是B的子类,那么C[A]是C[B]的子类,称为协变
C[-T]:如果A是B的子类,那么C[B]是C[A]的子类,称为逆变
C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系。称为不变.
比较器
Scala提供两个特质(trait)Ordered与Ordering用于比较。其中,Ordered混入(mix)Java的Comparable接口,而Ordering则混入Comparator接口。众所周知,在Java中
实现Comparable接口的类,其对象具有了可比较性;
实现comparator接口的类,则提供一个外部比较器,用于比较两个对象。
Ordered的用法和java中的Comparable接口一致 定义了单一的比较方式
Ordering的用法和java中的Comparator接口一致 可以自定义多中比较方式更灵活
ordered
trait Ordered[A] extends Any with java.lang.Comparable[A] {
/** Result of comparing `this` with operand `that`. * * Implement this method to determine how instances of A will be sorted. * * Returns `x` where: * * - `x < 0` when `this < that` * * - `x == 0` when `this == that` * * - `x > 0` when `this > that` * */
def compare(that: A): Int
/** Returns true if `this` is less than `that` */
def < (that: A): Boolean = (this compare that) < 0
/** Returns true if `this` is greater than `that`. */
def > (that: A): Boolean = (this compare that) > 0
/** Returns true if `this` is less than or equal to `that`. */
def <= (that: A): Boolean = (this compare that) <= 0
/** Returns true if `this` is greater than or equal to `that`. */
def >= (that: A): Boolean = (this compare that) >= 0
/** Result of comparing `this` with operand `that`. */
def compareTo(that: A): Int = compare(that)
}
object Ordered {
// 提供了由T到Ordered类型的隐式转换 隐式对象的转换
/** Lens from `Ordering[T]` to `Ordered[T]` */
implicit def orderingToOrdered[T](x: T)(implicit ord: Ordering[T]): Ordered[T] =
new Ordered[T] {
def compare(that: T): Int = ord.compare(x, that) }
}
自定义的类可以实现ordered特质来自定义排序
/** * 2019/11/18 * * @author Hangge.z WX:17710299606 * 姓名相同按照年龄排序 * 这种方式是单一的排序方式 */
class User (val name:String , val age:Int) extends Ordered[User]{
override def compare(that: User): Int = {
if( this.name.compareTo(that.name) == 0){
-(this.age - that.age)
}else{
this.name.compareTo(that.name)
}
}
// 重写toString
override def toString: String = {
s"$name : $age"}
}
object Test1 {
def main(args: Array[String]): Unit = {
val ls = List(new User("zs",21),new User("zs",34),new User("abc",23))
val res: List[User] = ls.sorted
res.foreach(println)
}
}
上面的方式可以实现排序但是排序方式单一 , Ordered提供了的隐式转换 ,这样自定义的类就不用实现Ordered接口 单一排序方式
object Test1 {
implicit def myOrders(user:User)={
new Ordered[User] {
override def compare(that: User) = {
if( user.name.compareTo(that.name) == 0){
-(user.age - that.age)
}else{
user.name.compareTo(that.name)
}
}
}
}
def main(args: Array[String]): Unit = {
val ls = List(new User("zs",21),new User("zs",34),new User("abc",23))
val res: List[User] = ls.sorted
res.foreach(println)
}
}
Ordering
class User2 (val name:String , val age:Int) {
// 重写toString
override def toString: String = {
s"$name : $age"}
}
类似于上面的隐式函数
val ls = List(new User2("zs",21),new User2("zs",34),new User2("abc",23))
// 隐式转换
implicit object Usero extends Ordering[User2]{
override def compare(x: User2, y: User2): Int = {
x.age - y.age
}
}
ls.sorted.foreach(println)
今天的文章scala柯里化和闭包_miller rabin算法「建议收藏」分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/85343.html