Scala进阶之路-Scala中的泛型介绍

                                   作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

  通俗的讲,比如需要定义一个函数,函数的参数可以接受任意类型。我们不可能一一列举所有的参数类型重载函数。那么程序引入了一个称之为泛型的东西,这个类型可以代表任意的数据类型。说白了泛型就是对数据类型的约束,例如 List,在创建 List 时,可以传入整形、字符串、浮点数等等任意类型。那是因为 List 在类定义时引用了泛型。

一.Scala中的泛型

 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.genericParadigm import cn.org.yinzhengjie.genericParadigm.ClothesEnum.ClothesEnum /**
* 泛型: 就是类型约束
* 定义一个泛型类Message
*/
abstract class Message[C](content: C)
/**
* 我们在继承发型类时,可以自定义传入的值,比如下面两个继承子类
*/
class StrMessage(content: String) extends Message(content) class IntMessage[Int](content: Int) extends Message[Int](content)
/**
* 定义一个泛型类Clothes,主构造方法有3个。
*/
class Clothes[A, B, C](val clothType: A, val color: B, val size: C)
/**
* 定义一个枚举类ClothesEnum,它需要继承Enumeration
*/
object ClothesEnum extends Enumeration {
type ClothesEnum = Value
val 上衣, 内衣, 裤子 = Value
} object ScalaGenericParadigm {
def main(args: Array[String]): Unit = {
val clth1 = new Clothes[ClothesEnum, String, Int](ClothesEnum.上衣, "black", 175)
println(clth1.clothType) val clth2 = new Clothes[ClothesEnum, String, String](ClothesEnum.上衣, "black", "XL")
println(clth2.size) val neiYi = new Clothes[ClothesEnum, String, String](ClothesEnum.内衣, "Pink", "X")
println(neiYi.color)
}
} /*
以上代码执行结果如下:
上衣
XL
Pink
*/

二.Scala的类型约束

1>.上界下界的图解说明

2>.类型约束的上界(Upper bounds)

 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie /**
* <:     #表示的是Scala泛型中的上界,相当于Java泛型中的"<T extends Comparable>"
* T<: Comparable[T] #表示T实现Comparable接口,不会发生隐式转换,除非用户显示的指定
*/
class ComparableGeneralObject[T<: Comparable[T]](a:T,b:T){
/**
* @return : 返回比较大的数值
*/
def bigger = {
if (a.compareTo(b) > 0){
a
}else{
b
}
}
} object ScalaUpperLowerBounds {
def main(args: Array[String]): Unit = { val res1 = new ComparableGeneralObject(Integer.valueOf(10),Integer.valueOf(20))
println(s"res1 ====> ${res1.bigger} ")
/**
* 注意,Predef.scala中有定义隐式方法,它可以把int转换成Integer,类似我们在java所说的自动拆箱和装箱。
* 而Predef在scala包下,因此其默认是导入的!
* 对了,还有一点就是上线界定不会隐式转换,因此我们在定义res2对象时,需要显示的指定其泛型,否则会编译不通过哟!
*/
val res2 = new ComparableGeneralObject[Integer](50,100)
println(s"res2 ====> ${res2.bigger} ") }
} /*
以上代码执行结果如下:
res1 ====> 20
res2 ====> 100
*/
 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie /**
* <:  #表示的是Scala泛型中的上界,相当于Java泛型中的"<T extends Comparable>"
* T<: Comparable[T] #表示T实现Comparable接口,不会发生隐式转换,除非用户显示的指定
*/
class ComparableGeneralObject[T<: Comparable[T]](a:T,b:T){
/**
* @return : 返回比较大的数值
*/
def bigger = {
if (a.compareTo(b) > 0){
a
}else{
b
}
}
} class TeacherOrdered(val name:String,val age:Int) extends Ordered[TeacherOrdered] {
/**
* 重写比较的方法,比较方法按照年龄来比较
*/
override def compare(that: TeacherOrdered): Int = {
this.age - that.age
}
/**
* 重写toString方法
*/
override def toString: String = {
this.name + "\t" + this.age
}
} object TeacherDemo{
def main(args: Array[String]): Unit = {
/**
* 丹尼斯·里奇,C语言之父,UNIX之父。曾担任朗讯科技公司贝尔实验室下属的计算机科学研究中心系统软件研究部的主任一
* 职。1978年与布莱恩·科尔尼干(Brian W. Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》,
* 现在此书已翻译成多种语言,成为C语言方面最权威的教材之一。2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,
* 享年70岁。
*/
val t1 = new TeacherOrdered("丹尼斯·里奇", 70)
/**
* 林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds, 1969年~ ),著名的电脑程序员、黑客。
* Linux内核的发明人及该计划的合作者。托瓦兹利用个人时间及器材创造出了这套当今全球最流行的操作系统
* (作业系统)内核之一。现受聘于开放源代码开发实验室(OSDL:Open Source Development Labs, Inc),
* 全力开发Linux内核。
*/
val t2 = new TeacherOrdered("Linus Benedict Torvalds", 49) val res1 = new ComparableGeneralObject(t1,t2)
println(res1.bigger)
}
} /*
以上代码执行结果如下:
丹尼斯·里奇 70
*/

通过类型约束的上界来比较对象的大小案例一

3>.类型约束的下界(Lower bounds)

  类型的约束下界貌似不太好使哟,不推荐使用!目前也没有找到相关可靠的资源!

三.Scala中的视图界定(view bounds

  "<%"的意思是“view bounds”(视界),它比<:适用的范围更广,除了所有的子类型,还允许隐式转换过去的类型。

 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie /**
* <% 是视图界定(view bounds)的标记,他会发生隐式转换
*/
class ComparableObject[T <% Comparable[T]](a:T,b:T){
/**
* @return : 返回比较大的数值
*/
def bigger = {
if (a.compareTo(b) > 0){
a
}else{
b
}
}
} class TeacherOrdered(val name:String,val age:Int) extends Ordered[TeacherOrdered] {
/**
* 重写比较的方法,比较方法按照年龄来比较
*/
override def compare(that: TeacherOrdered): Int = {
this.age - that.age
}
/**
* 重写toString方法
*/
override def toString: String = {
this.name + "\t" + this.age
}
} object TeacherDemo{
def main(args: Array[String]): Unit = {
/**
* 丹尼斯·里奇,C语言之父,UNIX之父。曾担任朗讯科技公司贝尔实验室下属的计算机科学研究中心系统软件研究部的主任一
* 职。1978年与布莱恩·科尔尼干(Brian W. Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》,
* 现在此书已翻译成多种语言,成为C语言方面最权威的教材之一。2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,
* 享年70岁。
*/
val t1 = new TeacherOrdered("丹尼斯·里奇", 70)
/**
* 林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds, 1969年~ ),著名的电脑程序员、黑客。
* Linux内核的发明人及该计划的合作者。托瓦兹利用个人时间及器材创造出了这套当今全球最流行的操作系统
* (作业系统)内核之一。现受聘于开放源代码开发实验室(OSDL:Open Source Development Labs, Inc),
* 全力开发Linux内核。
*/
val t2 = new TeacherOrdered("Linus Benedict Torvalds", 49) val res1 = new ComparableGeneralObject(t1,t2)
println(res1.bigger)
}
} /*
以上代码执行结果如下:
丹尼斯·里奇 70
*/
 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie /**
* <% #是视图界定(view bounds)的标记,他会发生隐式转换
*/
class ComparableGeneralObject[T<% Ordered[T]](a:T,b:T){
/**
* @return : 返回比较大的数值
*/
def bigger = {
if (a > b){
a
}else{
b
}
}
} /**
* 改类需要实现Ordered特质
*/
class TeacherOrdered(val name:String,val age:Int) {
/**
* 重写toString方法
*/
override def toString: String = {
this.name + "\t" + this.age
}
} object TeacherDemo{
/**
* 隐式将Teacher转换成Ordered
*/
implicit def TeacherToOrderedTeacher(t:TeacherOrdered) = new Ordered[TeacherOrdered]{
override def compare(that: TeacherOrdered): Int = {
t.age - that.age
}
} def main(args: Array[String]): Unit = {
/**
* 丹尼斯·里奇,C语言之父,UNIX之父。曾担任朗讯科技公司贝尔实验室下属的计算机科学研究中心系统软件研究部的主任一
* 职。1978年与布莱恩·科尔尼干(Brian W. Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》,
* 现在此书已翻译成多种语言,成为C语言方面最权威的教材之一。2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,
* 享年70岁。
*/
val t1 = new TeacherOrdered("丹尼斯·里奇", 70)
/**
* 林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds, 1969年~ ),著名的电脑程序员、黑客。
* Linux内核的发明人及该计划的合作者。托瓦兹利用个人时间及器材创造出了这套当今全球最流行的操作系统
* (作业系统)内核之一。现受聘于开放源代码开发实验室(OSDL:Open Source Development Labs, Inc),
* 全力开发Linux内核。
*/
val t2 = new TeacherOrdered("Linus Benedict Torvalds", 49) /**
* 注意,由于比较的方法是由视图界定实现,因此它会自动调用隐式实现,即调用上面的“implicit def TeacherToOrderedTeacher(t:TeacherOrdered)...”函数签名。
*/
val res1 = new ComparableGeneralObject(t1,t2)
println(res1.bigger)
}
} /*
以上代码执行结果如下:
丹尼斯·里奇 70
*/

视图界定(view bounds)+ 隐式转换改写以上代码的实现

 

四.cala中的上下文界定(context bounds)

  与 view bounds 一样 context bounds(上下文界定)也是隐式参数的语法糖。为语法上的方便,引入了”上下文界定”这个概念。

 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie /**
* 上下文界定也会发生隐式转换,比如我们定义柯里化函数(Currying)传递Ordering比较器,
* 相当于Java中的Compatrator比较器。
*/
class ComparableGeneralObject[T:Ordering](a:T,b:T)(implicit comparator:Ordering[T]){
/**
* @return : 返回比较大的数值
*/
def bigger:T = {
if (comparator.compare(a,b) > 0){
a
}else{
b
}
}
} /**
* 改类需要实现Ordered特质
*/
class TeacherOrdering(val name:String,val age:Int) {
/**
* 重写toString方法
*/
override def toString: String = {
this.name + "\t" + this.age
}
} object TeacherDemo{
/**
* 隐式创建一个比较器Ordering
*/
implicit val comparator= new Ordering[TeacherOrdering]{
override def compare(x: TeacherOrdering, y: TeacherOrdering): Int = {
x.age - y.age
}
} def main(args: Array[String]): Unit = {
/**
* 丹尼斯·里奇,C语言之父,UNIX之父。曾担任朗讯科技公司贝尔实验室下属的计算机科学研究中心系统软件研究部的主任一
* 职。1978年与布莱恩·科尔尼干(Brian W. Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》,
* 现在此书已翻译成多种语言,成为C语言方面最权威的教材之一。2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,
* 享年70岁。
*/
val t1 = new TeacherOrdering("丹尼斯·里奇", 70)
/**
* 林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds, 1969年~ ),著名的电脑程序员、黑客。
* Linux内核的发明人及该计划的合作者。托瓦兹利用个人时间及器材创造出了这套当今全球最流行的操作系统
* (作业系统)内核之一。现受聘于开放源代码开发实验室(OSDL:Open Source Development Labs, Inc),
* 全力开发Linux内核。
*/
val t2 = new TeacherOrdering("Linus Benedict Torvalds", 49) /**
* 注意,由于比较的方法是由视图界定实现,因此它会自动调用隐式实现,即调用上面的“implicit def TeacherToOrderedTeacher(t:TeacherOrdered)...”函数签名。
*/
val res1 = new ComparableGeneralObject(t1,t2)
println(res1.bigger)
}
} /*
以上代码执行结果如下:
丹尼斯·里奇 70
*/
 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie /**
* 上下文界定也会发生隐式转换,上下文界定是视图界定的语法糖
*/
class ComparableGeneralObject[T:Ordering](a:T,b:T){
/**
* @return : 返回比较大的数值
*/
def bigger:T = {
def inner(implicit comparator:Ordering[T]) = comparator.compare(a,b)
if (inner > 0){
a
}else{
b
}
}
} /**
* 改类需要实现Ordered特质
*/
class TeacherOrdering(val name:String,val age:Int) {
/**
* 重写toString方法
*/
override def toString: String = {
this.name + "\t" + this.age
}
} object TeacherDemo{
/**
* 隐式创建一个比较器Ordering
*/
implicit val comparator= new Ordering[TeacherOrdering]{
override def compare(x: TeacherOrdering, y: TeacherOrdering): Int = {
x.age - y.age
}
} def main(args: Array[String]): Unit = {
/**
* 丹尼斯·里奇,C语言之父,UNIX之父。曾担任朗讯科技公司贝尔实验室下属的计算机科学研究中心系统软件研究部的主任一
* 职。1978年与布莱恩·科尔尼干(Brian W. Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》,
* 现在此书已翻译成多种语言,成为C语言方面最权威的教材之一。2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,
* 享年70岁。
*/
val t1 = new TeacherOrdering("丹尼斯·里奇", 70)
/**
* 林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds, 1969年~ ),著名的电脑程序员、黑客。
* Linux内核的发明人及该计划的合作者。托瓦兹利用个人时间及器材创造出了这套当今全球最流行的操作系统
* (作业系统)内核之一。现受聘于开放源代码开发实验室(OSDL:Open Source Development Labs, Inc),
* 全力开发Linux内核。
*/
val t2 = new TeacherOrdering("Linus Benedict Torvalds", 49) /**
* 注意,由于比较的方法是由视图界定实现,因此它会自动调用隐式实现,即调用上面的“implicit def TeacherToOrderedTeacher(t:TeacherOrdered)...”函数签名。
*/
val res1 = new ComparableGeneralObject(t1,t2)
println(res1.bigger)
}
} /*
以上代码执行结果如下:
丹尼斯·里奇 70
*/

上下文界定是视图界定的语法糖

 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie /**
* 上下文界定也会发生隐式转换,上下文界定是视图界定的语法糖
*/
class ComparableGeneralObject[T:Ordering](a:T,b:T){
/**
* @return : 返回比较大的数值
*/
def bigger:T = {
val comparator = implicitly[Ordering[T]]
if (comparator.compare(a,b) > 0 ){
a
}else{
b
}
}
} /**
* 改类需要实现Ordered特质
*/
class TeacherOrdering(val name:String,val age:Int) {
/**
* 重写toString方法
*/
override def toString: String = {
this.name + "\t" + this.age
}
} object TeacherDemo{
/**
* 隐式创建一个比较器Ordering
*/
implicit val comparator= new Ordering[TeacherOrdering]{
override def compare(x: TeacherOrdering, y: TeacherOrdering): Int = {
x.age - y.age
}
} def main(args: Array[String]): Unit = {
/**
* 丹尼斯·里奇,C语言之父,UNIX之父。曾担任朗讯科技公司贝尔实验室下属的计算机科学研究中心系统软件研究部的主任一
* 职。1978年与布莱恩·科尔尼干(Brian W. Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》,
* 现在此书已翻译成多种语言,成为C语言方面最权威的教材之一。2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,
* 享年70岁。
*/
val t1 = new TeacherOrdering("丹尼斯·里奇", 70)
/**
* 林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds, 1969年~ ),著名的电脑程序员、黑客。
* Linux内核的发明人及该计划的合作者。托瓦兹利用个人时间及器材创造出了这套当今全球最流行的操作系统
* (作业系统)内核之一。现受聘于开放源代码开发实验室(OSDL:Open Source Development Labs, Inc),
* 全力开发Linux内核。
*/
val t2 = new TeacherOrdering("Linus Benedict Torvalds", 49) /**
* 注意,由于比较的方法是由视图界定实现,因此它会自动调用隐式实现,即调用上面的“implicit def TeacherToOrderedTeacher(t:TeacherOrdered)...”函数签名。
*/
val res1 = new ComparableGeneralObject(t1,t2)
println(res1.bigger)
}
} /*
以上代码执行结果如下:
丹尼斯·里奇 70
*/

使用implicitly优化以上代码

Scala进阶之路-Scala中的泛型介绍的更多相关文章

  1. Scala进阶之路-Scala中的高级类型

    Scala进阶之路-Scala中的高级类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类型(Type)与类(Class)的区别 在Java里,一直到jdk1.5之前,我们说 ...

  2. Scala进阶之路-Scala中的Ordered--Ordering

    Scala进阶之路-Scala中的Ordered--Ordering 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   说道对象的比较,在Java中大家最熟悉不过的就是实现类本身实 ...

  3. Scala进阶之路-Scala中的枚举用法案例展示

    Scala进阶之路-Scala中的枚举用法案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的枚举值和Java中的枚举值有点差别,不过使用起来也都差大同小异,我这 ...

  4. Scala进阶之路-Scala高级语法之隐式(implicit)详解

    Scala进阶之路-Scala高级语法之隐式(implicit)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一 ...

  5. Scala进阶之路-Scala特征类与unapply反向抽取

    Scala进阶之路-Scala特征类与unapply反向抽取 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Scala特征类分析 1>.Unit 答:用于定义返回值类型, ...

  6. Scala进阶之路-Scala函数篇详解

    Scala进阶之路-Scala函数篇详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传值调用和传名调用 /* @author :yinzhengjie Blog:http: ...

  7. Scala进阶之路-Scala的基本语法

    Scala进阶之路-Scala的基本语法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.函数式编程初体验Spark-Shell之WordCount var arr=Array( ...

  8. Scala进阶之路-高级数据类型之数组的使用

    Scala进阶之路-高级数据类型之数组的使用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数组的初始化方式 1>.长度不可变数组Array 注意:顾名思义,长度不可变数 ...

  9. Scala进阶之路-反射(reflect)技术详解

    Scala进阶之路-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的反射技术和Java反射用法类似,我这里就不一一介绍反射是啥了,如果对 ...

随机推荐

  1. 实训十二(stick的设定)

    上篇我们介绍到人物主角的设定,其实人物是有工具使的,那就是——stick小棍. 信息的获取.起始位置.长度的加载.边界的判断.位置.长度重置是需要我们主要考虑的问题 信息获取上考虑的使什么时候加载st ...

  2. Java设计模式之工厂模式(Factory模式)介绍(转载)

    原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工 ...

  3. 如何根据元素的className获取元素?

    getElementsByClassName()是HTML5 新增的DOM API.IE8以下不支持 我们知道,原生的方法,是getElementById()和getElementsByTagName ...

  4. NodeJS中的require和import

    ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引入模块,使 ...

  5. xhtml和html的差別

    xhtml和html主要區別: 元素必須正確嵌套: 元素必須正確閉合: 必須要有根元素: 元素必須使用小寫. xhtml語法: 屬性名必須小寫: 屬性值必須帶引號: 使用id代替name: lang屬 ...

  6. Essential Phone PH1官方刷机方法

    Essential Phone官方有两种包 一种是ota包,即sideload线刷使用的包.但此刷机方法只能ota升级,不能降级. 另一种是Images包,即fastboot线刷使用的包.这种方法可以 ...

  7. codeforces706C

    Hard problem CodeForces - 706C 现在有 n 个由小写字母组成的字符串.他想要让这些字符串按字典序排列,但是他不能交换任意两个字符串.他唯一能做的事是翻转字符串. 翻转第  ...

  8. POJ2492-A Bug's Life-并查集扩展应用

    维护一个relation数组,保留着此元素和根元素之间的性别关系.之后就可以判断gay了. #include <cstdio> #include <algorithm> #in ...

  9. Spring bean默认为单例模式会引发并发问题吗

    在web项目中使用spring,如果网站同时很多人访问,这时候使用spring默认的单例模式的bean是否合适呢?回不回影响效率或者产生交叉呢? Spring默认的单例模式的bean,因为是单例的,所 ...

  10. 10 Zabbix Item类型之Zabbix IPMI类型

    点击返回:自学Zabbix之路 Zabbix Item类型之Zabbix IPMI类型 一般使用zabbix IPMI 监控硬件信息,比如说温度. 在编译安装zabbix server的时候,一定要加 ...