Scala 语言学习之泛型(7)
==>泛型类
---> T可以代表任意类型
classPerson[T]{privatevarname:T=_defsetName(name:T)={this.name=name}defgetName():T={this.name}}//***********测试*****************objectPerson{defmain(args:Array[String]):Unit={varp=newPerson[String]()p.setName("hello")println(p.getName())}}
==>泛型函数
--->类型参数放在方法名之后
//*泛型函数//创建一个固定类型的数组//普通函数defmkInt(elems:Int*)=Array[Int](elems:_*)defmkString(str:String*)="mkString"//使用泛型函数,可以接收任意类型defmkArray[T:ClassTag](elems:T*)=Array[T](elems:_*)//***********测试*****************//普通函数只能传入相对应类型的参数mkInt(1,2,3)mkString("hello","world")//泛型函数可以传入任意类型的参数mkArray(11.26,665,84,"hello")
==>类型的上界和下界(Upper Bounds和 Lower Bounds)
--->用来定义泛型变量的范围 :
--->S <: T (上界)S必须是T类型的子类或类本身
classPerson1{defgender()={println("gender")}}classManextendsPerson1{overridedefgender()={println("man")}}classWomenextendsPerson1{overridedefgender()={println("women")}
objectUpperBoundsAndLowerBounds{//定义一个泛型函数,通过上界的方式指定泛型的范围必须是Person1的子类或者Person1类,并调用类中的gender方法defgetGender[T<:Person1](g:T)={g.gender()}defmain(args:Array[String]):Unit={//创建一个Person1对象,调用getGender方法调用Personal中的gender方法varp:Person1=newPerson1getGender(p)//创建一个Man对象,通过getGender方法调用Man类中的gender方法varm=newMangetGender(m)}}
--->U >: T(下界)U必须是T类型的父类或类本身,此处不作示例,与上面例子类似,只是传入getGender方法中的参数必须是Person1类或其父类的对象
==>视图界定<%
--->与类型的上界相似,但是比类型的上界适用范围更广,除了所有的子类与类本身,它还允许通过隐式转换得到的类型
defint2String[T<%String](x:T,y:T)={println(x+"*****"+y)}//***********测试*****************int2String("hello","world")implicitdefint2String1(n:Int):String={n.toString}int2String(100,120)
==>协变和逆变
--->协变:泛型变量的值可以是子类或类本身在类型参数前加一个 “+”符号子类转换为父类
//*协变和逆变在类型的前面加入+号,就可以使类的特征变为协变了//将子类对象转换为父类对象称为协变+//将父类对象转换为子类对象称为逆变-packagedemo1{//父类classAnimal{}//子类classBirdextendsAnimalclassSparrowextendsBird//吃东西的类协变classEatSomethings[+T](t:T){}//***********测试*****************objectDemo1{defmain(args:Array[String]):Unit={//创建一个吃东西的对象varc1:EatSomethings[Sparrow]=newEatSomethings[Sparrow](newSparrow)varc2:EatSomethings[Animal]=c1}}}
--->逆变:泛型变量的值可以是父类或类本身在类型参数前加一个 “-”符号父类转换为子类例:省略
==>隐式转换函数
--->以关键字implicit 申明
--->单个参数
classFruit(name:String){defgetFruitName():String={name}}classMonkey(f:Fruit){defsay()={println("Monkeylike"+f.getFruitName())}}//***********测试*****************objectImplicitDemo{defmain(args:Array[String]):Unit={varf:Fruit=newFruit("bnanan")//调用fruit的方法,希望Monkey这个say方法来实现//需要将fruit的对象转换为monkey对象,即定义一个隐匿转换函数implicitdeffruit2Monkey(f:Fruit):Monkey={newMonkey(f)}//将fruit对象转换为Monkey对象//调用Monkey中的say方法f.say()}}
==>隐式参数使用implicit关键字申明的函数参数
--->可以使用隐式参数进行类型转换
//隐式参数deftestParam(implicitname:String)={println("Thevalueis"+name)}implicitvalname:String="这是一个隐式值"//***********测试*****************testParam//---------------------------------------------------------------//带隐式参数的泛型函数//Ordered[T]使类型可排序,//原型:defsmaller//(implicitorder:T=>Ordered[T])defsmaller[T](a:T,b:T)(implicitorder:T=>Ordered[T])=if(order(a)<b)aelseb//***********测试*****************smaller(100,56)smaller("hello","hi")
==>隐式类对类 增加 implicit限定 的类,其主要作用就是对类的功能增强
--->编写一个隐式类,使类实现更多的功能
objecttestImplicit{//定义一个隐式类implicitclassCalc(x:Int){defadd(a:Int):Int=a+x}//***********测试*****************defmain(args:Array[String]):Unit={println("两个数字的和:"+1.add(2))}}
--->程序过程分析:
---当 1.add(2)时,scala的编译器不会报错,在当前域中查找,有没有 implicit修饰的,同时可以将Int作为参数的构造器,并且具有 add方法的类,通过查找,找到Calc
---利用隐式类Calc来执行add方法
==>个人总结:
---> 通过泛型,可以使我们定义一个模具,就像蛋糕的模具,我们可以分别放入草莓,蓝莓等不同的原料加工出不同口味的蛋糕来
--->通过使用上界,下界,视图界定,协变,逆变,对泛型的范围制定规则,使我们可以传入的符合规则的参数
--->隐式函数,隐式参数,隐式类,会在程序运行时首先被查找,若有符合以implicit修饰的参数,函数以及类,先执行,然后才运行程序
若总结有误,还请多多指教,谢谢!!!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。