Scala泛型、隐式转换和隐式参数、视图介绍、Scala中的上界、下界、结合柯里化进行隐式转换

本文主要是介绍Scala泛型、隐式转换和隐式参数、视图介绍、Scala中的上界、下界、结合柯里化进行隐式转换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

二、泛型

一、Scala泛型
1. 泛型介绍
泛型用于指定方法或类可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效地增强程序的适用性,使用泛型可以使得类或方法具有更强的通用性。泛型的典型应用场景是集合及集合中的方法参数,可以说同java一样,scala中泛型无处不在,具体可以查看scala的api。
2. 泛型类、泛型方法
泛型类:指定类可以接受任意类型参数。
泛型方法:指定方法可以接受任意类型参数。
3. 案例
案例一:

package cn.toto.gen/*** Created by toto on 2017/7/1.* 下面的意思就是表示只要是Comparable就可以传递,下面是类上定义的泛型*/
/*class MrRight[T <:Comparable[T]] {//定义一个选择方法,实现选择的功能def choose(first : T,second : T) : T = {if(first.compareTo(second) > 0) first else second}
}*//*** 在类上定义泛型可以,当然,也可以在方法上定义泛型,定义的方式如下:*/
class MrRight {def choose[T <: Comparable[T]](first:T,second:T) : T = {if(first.compareTo(second) > 0) first else second}
}object MrRight {def main(args: Array[String]): Unit = {
//    //如果是类上定义的泛型,通过下面的方式调用
//    val mr = new MrRight[Boy]
//    val b1 = new Boy("laoduan",99)
//    val b2 = new Boy("laozhao",9999)
//    val boy = mr.choose(b1,b2)
//    //结果是:laozhao
//    println(boy.name)//如果是在方法上定义的泛型,可以使用下面的方式:var mr = new MrRightval b1 = new Boy("laoduan",99)val b2 = new Boy("laozhao",9999)val boy = mr.choose[Boy](b1,b2)//结果同样是:laozhaoprintln(boy.name)}
}

案例二:

package cn.toto.scala.enhance/*** Created by toto on 2017/7/1.* 泛型类,泛型方法* 泛型用于指定方法或类可以接受任意类型参数* 参数在实际使用时才被确定* 泛型可以有效地增强程序的适用性* 使用泛型可以使用得类或方法具有更强的通用性*/
//泛型类    F S T是类型的参数
class GenericClass[F,S,T](val f:F,val s:S,val t:T)
object GenericDemo {//泛型方法def getData[T](list:List[T]) = list(list.length/2)/*** 运行结果:* 26* 3*/def main(args : Array[String]): Unit = {//实例化方式1val gc1 = new GenericClass("lisha",26,"beijing")//实例化方式2val gc2 = new GenericClass[String,String,Int]("lisha","beijing",26)println(getData(List("lisha",26,"beijing")))val t = getData[Int] _println(t(List(1,2,3,4,5)))}
}

二、 隐式转换和隐式参数

1. 概念
隐式转换和隐式参数是Scala中两个非常强大的功能,利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节。
2. 作用
隐式的对类的方法进行增强,丰富现有类库的功能
3. 隐式转换函数
是指那种以implicit关键字声明的带有单个参数的函数。

可以通过::implicit –v这个命令显示所有做隐式转换的类。
4. 隐式转换例子

package cn.toto.impliimport java.io.File
import scala.io.Source/*** 这个案例是为了一下读出文件中的内容,目的类似通过下面的read方法直接读取出其中的内容:* var file = new File("E:\\wordcount\\input\\1.txt");var contents = file.read();** Created by toto on 2017/7/1.* 隐式的增强File类的方法*/
class RichFile(val from : File){//定义一个read方法,返回def read() : String = Source.fromFile(from.getPath).mkString
}object RichFile {//隐式转换方法(将原有的File类型转成了file类型,在用的时候需要导入相应的包)implicit def file2RichFile(from : File) = new RichFile(from)
}object MainApp {def main(args: Array[String]): Unit = {val file = new File("E:\\wordcount\\input\\a.txt");//装饰模式,显示的增强(本来想实现:val contents = file.read(),但是却使用RichFile的方式,所以是显示的增强)val rf = new RichFile(file)val contents = rf.read();//目的是使用File的时候不知不觉的时候直接使用file.read()方法,所以这里就要做隐式转换//导入隐式转换,._将它下满的所有的方法都导入进去了。 导包的代码,可以import RichFile._//这里没有的read()方法的时候,它就到上面的这一行中的找带有implicit的定义方法var content = new File("E:\\wordcount\\input\\a.txt").readprintln()//import RichFile.file2RichFile//println(file2RichFile(new File("E:\\wordcount\\input\\1.txt")).read)}
}
package cn.toto.scalaimport java.awt.GridLayout/*** Created by ZX on 2015/11/13.*/
object ImplicitContext{//implicit def girl2Ordered(g : Girl) = new Ordered[Girl]{//  override def compare(that: Girl): Int = if (g.faceValue > that.faceValue) 1 else -1//}implicit object OrderingGirl extends Ordering[Girl]{
    override def compare(x: Girl, y: Girl): Int = if (x.faceValue > y.faceValue) 1 else -1}
}class Girl(var name: String, var faceValue: Double){override def toString: String = s"name : $name, faveValue : $faceValue"
}//class MissRight[T <% Ordered[T]](f: T, s: T){
//  def choose() = if(f > s) f else s
//}
//class MissRight[T](f: T, s: T){
//  def choose()(implicit ord: T => Ordered[T]) = if (f > s) f else s
//}class MissRight[T: Ordering](val f: T, val s: T){def choose()(implicit ord: Ordering[T]) = if(ord.gt(f, s)) f else s
}object MissRight {def main(args: Array[String]) {
    import ImplicitContext.OrderingGirl
    val g1 = new Girl("yuihatano", 99)
    val g2 = new Girl("jzmb", 98)
    val mr = new MissRight(g1, g2)
    val result = mr.choose()
    println(result)}
}

视图介绍

隐含参数和方法也可以定义隐式转换,称作视图。视图的绑定从另一个角度看就是implicit的转换。主要用在两个场合:
当一个T类型的变量t要装换成A类型时
当一个类型T的变量t无法拥有A类型的a方法或变量时
其实视图的绑定是为了更方便的使用隐式装换
用符号 <% 表示。

Scala中的上界、下界

1.上界、下界介绍
在指定泛型类型时,有时需要界定泛型类型的范围,而不是接收任意类型。比如,要求某个泛型类型,必须是某个类的子类,这样在程序中就可以放心的调用父类的方法,程序才能正常的使用与运行。此时,就可以使用上下边界Bounds的特性;
Scala的上下边界特性允许泛型类型是某个类的子类,或者是某个类的父类;

(1) U >: T

这是类型下界的定义,也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。

(2) S <: T

这是类型上界的定义,也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类)。

下面是视图介绍和上界、下界的示例代码:
下面定义两个类

package cn.toto.gen/*** Created by toto on 2017/7/1.*/
class Boy(val name : String,var faceVlue : Int) extends Comparable[Boy] {override def compareTo(o: Boy): Int = {this.faceVlue - o.faceVlue}
}
package cn.toto.gen/*** Created by toto on 2017/7/1.*/
class Girl(val name:String,var faceValue:Int) {}
这里写代码片
package cn.toto.genimport java.awt.GridLayout
import java.io.Fileimport cn.toto.impli.RichFile/*** Created by ZhaoXing on 2016/8/18.*/
object MyPreDef {//针对viewbound方式的
//  implicit def girl2Ordered(g : Girl) = new Ordered[Girl] {
//    override def compare(that: Girl): Int = {
//      g.faceValue - that.faceValue
//    }
//  }//针对Ordering类型的implicit object Girl2Ordering extends Ordering[Girl] {override def compare(x: Girl, y: Girl): Int = {x.faceValue - y.faceValue}}
}
package cn.toto.gen/*** Created by toto on 2017/7/1.* 下面的意思就是表示只要是Comparable就可以传递,下面是类上定义的泛型*/
/*class MrRight[T <:Comparable[T]] {//定义一个选择方法,实现选择的功能def choose(first : T,second : T) : T = {if(first.compareTo(second) > 0) first else second}
}*//*** 在类上定义泛型可以,当然,也可以在方法上定义泛型,定义的方式如下:*/
class MrRight {def choose[T <: Comparable[T]](first:T,second:T) : T = {if(first.compareTo(second) > 0) first else second}
}object MrRight {def main(args: Array[String]): Unit = {
//    //如果是类上定义的泛型,通过下面的方式调用
//    val mr = new MrRight[Boy]
//    val b1 = new Boy("laoduan",99)
//    val b2 = new Boy("laozhao",9999)
//    val boy = mr.choose(b1,b2)
//    //结果是:laozhao
//    println(boy.name)//如果是在方法上定义的泛型,可以使用下面的方式:var mr = new MrRightval b1 = new Boy("laoduan",99)val b2 = new Boy("laozhao",9999)val boy = mr.choose[Boy](b1,b2)//结果同样是:laozhaoprintln(boy.name)}
}
package cn.toto.gen/*** Created by toto on 2017/7/1.*/
//viewbound必须存在一个隐式转换方法,视图界定,必须有一个隐式转换的方法
//class MissRight[T <% Ordered[T]] {
//  def choose(first:T,second : T) : T = {
//    //这里的之所以可以用'>',是因为这里的T可以转换成Order的类型
//    if(first > second) first else second
//  }
//}//如果使用上下文界定,必须存在一个隐式转换的值,特点是使用Ording,但是不需要使用Ordering[T]
class MissRight[T : Ordering] {def select(first : T,second : T) : T = {//通过使用implicitly转换类型val ord = implicitly[Ordering[T]]if(ord.gt(first,second)) first else second}
}object MissRight {def main(args: Array[String]): Unit = {def main(args: Array[String]): Unit = {//这里是使用viewbound方式的。
//      import MyPreDef._
//      val mr = new MissRight[Girl]
//      val g1 = new Girl("ab",90)
//      val g2 = new Girl("aaa",999)
//      val g = mr.choose(g1,g2)
//      println(g.name)//这里是针对Order类型的import MyPreDef._val mr = new MissRight[Girl]val g1 = new Girl("ab",90)val g2 = new Girl("aaa",999)val g = mr.select(g1,g2)println(g.name)}}
}

结合柯里化进行隐式转换:
代码如下:

package cn.com.toto.gen/*** Created by toto on 2017/7/2.*/
class Girl(val name : String,var faceValue:Int) {}
package cn.com.toto.genimport cn.toto.impli.RichFile/*** Created by toto on 2017/7/2.*/
object MyPreDef {implicit object Girl2Ordering extends Ordering[Girl] {override def compare(x: Girl, y: Girl): Int = {x.faceValue - y.faceValue}}
}
package cn.com.toto.gen/*** Created by toto on 2017/7/2.*/
class MissR[T] {//如果利用柯里化传入一个隐式转换函数,其作用和Viewbound是一样的,都需要一个隐式转换方法或函数def choose(f: T, s: T)(implicit ord: T => Ordered[T]) : T = {if (f > s) f else s}//如果利用柯里化传入一个隐式的类型, 其作用和Contextbound是一样的,都需要一个隐式转换的值def select(f: T, s: T)(implicit ord: Ordering[T]) : T = {if(ord.gt(f, s)) f else s}def random(f: T, s: T)(implicit ord: Ordering[T]) : T = {import Ordered.orderingToOrderedif(f > s) f else s}
}object MissR {def main(args : Array[String]): Unit = {import MyPreDef._val mr = new MissR[Girl]val g1 = new Girl("aaa", 80)val g2 = new Girl("bbb", 90)//val g = mr.choose(g1, g2)val g = mr.random(g1, g2)//运行结果是:bbbprintln(g.name)}
}

这篇关于Scala泛型、隐式转换和隐式参数、视图介绍、Scala中的上界、下界、结合柯里化进行隐式转换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/918274

相关文章

5 种使用Python自动化处理PDF的实用方法介绍

《5种使用Python自动化处理PDF的实用方法介绍》自动化处理PDF文件已成为减少重复工作、提升工作效率的重要手段,本文将介绍五种实用方法,从内置工具到专业库,帮助你在Python中实现PDF任务... 目录使用内置库(os、subprocess)调用外部工具使用 PyPDF2 进行基本 PDF 操作使用

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型

Java轻松实现PDF转换为PDF/A的示例代码

《Java轻松实现PDF转换为PDF/A的示例代码》本文将深入探讨Java环境下,如何利用专业工具将PDF转换为PDF/A格式,为数字文档的永续保存提供可靠方案,文中的示例代码讲解详细,感兴趣的小伙伴... 目录为什么需要将PDF转换为PDF/A使用Spire.PDF for Java进行转换前的准备通过

Python进行word模板内容替换的实现示例

《Python进行word模板内容替换的实现示例》本文介绍了使用Python自动化处理Word模板文档的常用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录技术背景与需求场景核心工具库介绍1.获取你的word模板内容2.正常文本内容的替换3.表格内容的

Git进行版本控制的实战指南

《Git进行版本控制的实战指南》Git是一种分布式版本控制系统,广泛应用于软件开发中,它可以记录和管理项目的历史修改,并支持多人协作开发,通过Git,开发者可以轻松地跟踪代码变更、合并分支、回退版本等... 目录一、Git核心概念解析二、环境搭建与配置1. 安装Git(Windows示例)2. 基础配置(必

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

HTTP 与 SpringBoot 参数提交与接收协议方式

《HTTP与SpringBoot参数提交与接收协议方式》HTTP参数提交方式包括URL查询、表单、JSON/XML、路径变量、头部、Cookie、GraphQL、WebSocket和SSE,依据... 目录HTTP 协议支持多种参数提交方式,主要取决于请求方法(Method)和内容类型(Content-Ty