标签:this 继承 实例 collect 接口 upper 等等 原来 要求
1) 如果我们要求函数的参数可以接受任意类型,可以使用泛型,这个类型可以代表任意的数据类型
2) 例如List,在创建List时,可以传入整型、字符串、浮点数等等任意类型。那是因为List在类定义时引用了泛型。比如在Java中:public interface List<E> extends Collection<E>
-要求
1) 编写一个Message类
2) 可以构建Int类型的Message,String类型的Message
3) 要求使用泛型来完成设计(说明:不能使用Any)
-案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val intMessage = new IntMessage[Int](10) println(intMessage) val strMessage = new StringMessage[String]("hello") println(strMessage) } } /* 编写一个Message类 可以构建Int类型的Message, String类型的Message. 要求使用泛型来完成设计,(说明:不能使用Any) */ abstract class Message[T](s: T) { def get = s } class IntMessage[Int](v: Int) extends Message(v) class StringMessage[String](v: String) extends Message(v)
-要求
1) 定义一个函数,可以获取各种类型的List的中间index的值
2) 使用泛型完成
-案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val list1 = List("hello", "Tom", "world") val list2 = List(90, 10, 23) println(midList[String](list1)) // "Tom" println(midList[Int](list2)) // 10 } /* 要求 定义一个函数,可以获取各种类型的 List 的中间index的值 使用泛型完成 */ def midList[E](l: List[E]): E = { l(l.length / 2) } }
-Java中上界
在Java泛型里表示某个类型是A类型的子类型,使用extends关键字,这种形式叫upper bounds(上限或上界),语法如下:
<T extends A> //或用通配符的形式: <? extends A>
-Scala中上界
在Scala里表示某个类型是A类型的子类型,也称上界或上限,使用 <: 关键字,语法如下:
[T<:A] //或用通配符: [_ <: A]
-Scala中上界应用案例-要求
1) 编写一个通用的类,可以进行Int之间、Folat之间,等实现了Comparable接口的值直接的比较.//java.lang.Integer
2) 分别使用传统方法和上界的方式来完成,体会上界使用的好处
3) 案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val compareInt = new CompareInt(10,40) println(compareInt.greater) // 40 //第一个用法 val commonCompare1 = new CommonCompare(Integer.valueOf(12), Integer.valueOf(36))//Int println(commonCompare1.greater) //第二个用法 val commonCompare2 = new CommonCompare(java.lang.Float.valueOf(1.6f), java.lang.Float.valueOf(2.7f))//Fl println(commonCompare2.greater) //第3种写法使用了隐式转换 //implicit def float2Float(x: Float): java.lang.Float = x.asInstanceOf[java.lang.Float] val commonCompare3 = new CommonCompare[java.lang.Float](12.1f, 23.1f)// println(commonCompare3.greater) } } /* 编写一个通用的类,可以进行Int之间、Float之间,等实现了Comparable接口的值直接的比较.//java.lang.Integer 分别使用传统方法和上界的方式来完成,体会上界使用的好处. */ //传统方法 class CompareInt(n1: Int, n2: Int) { //返回较大的值 def greater = if(n1 > n2) n1 else n2 } //使用上界(上限)来完成 //说明 //1. [T <: Comparable[T]] 表示T类型是Comparable 子类型 //2. 即你传入的T类要继承Comparable接口 //3. 这样就可以使用compareTo方法 //4. 这样的写法(使用上界的写法)通用性比传统的好 class CommonCompare[T <: Comparable[T]](obj1:T,obj2:T) { def greater = if (obj1.compareTo(obj2) > 0) obj1 else obj2 }
-Java中下界
在Java泛型里表示某个类型是A类型的父类型,使用super关键字,语法如下:
<T super A> //或用通配符的形式: < ? super A>
-Scala中下界
在Scala的下界或下限,使用 >: 关键字,语法如下:
[T >: A] //或用通配符: [_ >: A]
-Scala中下界应用案例
//1)和Animal直系的,是Animal父类的还是父类处理,是Animal子类的按照Animal处理(), //2)和Animal无关的,一律按照Object处理! object boke_demo01 { def main(args: Array[String]): Unit = { println("ok!") //满足下界的约束 biophony(Seq(new Earth, new Earth)).map(_.sound()) //满足下界的约束 biophony(Seq(new Animal, new Animal)).map(_.sound()) //这里我们不能使用上界的思路去推导,这里是可以运行 //1.? println("===================") biophony(Seq(new Bird, new Bird)).map(_.sound()) // // biophony(Seq(new Moon)) } //下界 def biophony[T >: Animal](things: Seq[T]) = things } class Earth { //Earth 类 def sound() { //方法 println("hello !") } } class Animal extends Earth { override def sound() = { //重写了Earth的方法sound() println("animal sound") } } class Bird extends Animal { override def sound() = { //将Animal的方法重写 print("bird sounds") } } class Moon { // def sound()={ //将Animal的方法重写 // print("bird sounds") // } }
-Scala中下界的使用小结
1) 对于下界,可以传入任意类型
2) 传入和Animal直系的,是Animal父类的还是父类处理,是Animal子类的按照Animal处理
3) 和Animal无关的,一律按照Object处理
4) 也就是下界,可以随便传,只是处理方式不一样
5) 不能使用上界的思路来类推下界的含义
-说明:隐式转换结合视图界定的方式,比较两个Person对象的年龄大小
object boke_demo01 { def main(args: Array[String]): Unit = { //使用了隐式转换 val compareComm1 = new CompareComm(7, 23) println(compareComm1.greater) val compareComm2 = new CompareComm(Integer.valueOf(20), Integer.valueOf(30)) println(compareComm2.greater) //以前 <: 上界 val compareComm3 = new CompareComm[java.lang.Float](201.9f, 27.1f) println(compareComm3.greater) //上面的小数比较,在视图界定的情况下,就可以这样写了 //这里会进行隐式转换 val compareComm4 = new CompareComm(201.9f, 360.1f) println(compareComm4.greater) } } //说明 //1. T <% Comparable[T] 说明 T是 Comparable子类型 //2. T <% Comparable[T] 和 T <: Comparable[T] 区别就是视图界定支持隐式转换 //3. 视图界定不但支持以前上界的写法,同时支持简洁的写法val compareComm1 = new CompareComm(1, 20) class CompareComm[T <% Comparable[T]](obj1: T, obj2: T) { def greater = if (obj1.compareTo(obj2) > 0) obj1 else obj2 }
与view bounds一样context bounds(上下文界定)也是隐式参数的语法糖。为了语法上的方便,引用了“上下文这个概念”
-要求:使用上下文界定+隐式参数的方式,比较两个Person对象的年龄大小。使用Ordering实现比较
-案例演示
object boke_demo01 { //这里我定义一个隐式值 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("Tom", 30) val p2 = new Person4("Jack", 35) val compareComm4 = new CompareComm4(p1, p2) println(compareComm4.geatter) // "Jack", 35 val compareComm5 = new CompareComm5(p1, p2) println(compareComm5.geatter) // "Jack", 35 println("personComparetor hashcode=" + personComparetor.hashCode()) val compareComm6 = new CompareComm6(p1, p2) println(compareComm6.geatter) // "Jack", 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 else obj2 } //方式2 //方式2,将隐式参数放到方法内 class CompareComm5[T: Ordering](o1: T, o2: T) { def geatter = { def f1(implicit cmptor: Ordering[T]) = cmptor.compare(o1, o2) //返回一个数字 //如果f1返回的值>0,就返回o1,否则返回o2 if (f1 > 0) o1 else o2 } def lowwer = { def f1(implicit cmptor: Ordering[T]) = cmptor.compare(o1, o2) //返回一个数字 //如果f1返回的值>0,就返回o2,否则返回o1 if (f1 > 0) o2 else o1 } } //方式3 //方式3,使用implicitly语法糖,最简单(推荐使用) class CompareComm6[T: Ordering](o1: T, o2: T) { def geatter = { //这句话就是会发生隐式转换,获取到隐式值 personComparetor //底层仍然使用编译器来完成绑定(赋值的)工作 val comparetor = implicitly[Ordering[T]] println("comparetor hashcode=" + comparetor.hashCode()) if (comparetor.compare(o1, o2) > 0) o1 else o2 } }
1) Scala的协变(+),逆变(-),协变covariant、逆变contravariant、不可变invariant
2) 对于一个带类型参数的类型,比如List[T],如果对A及其子类型B,满足List[B]也符合List[A]的子类型,那么就称为covariance(协变),如果List[A]是List[B]的子类型,即与原来的父子关系正相反,则称为contravariance(逆变)。如果一个类型支持协变和逆变,则称这个类型为variance(可变的),否则称为invariance(不可变的)
3) 在Java里,泛型类型都是invariant,比如List<String>并不是List<Object>的子类型。而Scala支持,可以在定义类型时声明(用加号表示协变,减号表示逆变),如:trait List[+T]//在类型定义时声明为协变这样会把List[String]作为List[Any]的子类型
-说明:在这里引入关于这个符号的说明,在声明Scala的泛型类型时,“+”表示协变,而“-”表示逆变
1) C[+T]:如果A是B的子类,那么C[A]是C[B]的子类,称为协变
2) C[-T]:如果A是B的子类,那么C[B]是C[A]的子类,称为逆变
3) C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系,称为不变
-案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val t1: Temp3[Sub] = new Temp3[Sub]("hello");//ok val t2: Temp3[Sub] = new Temp3[Super]("hello");//error val t3: Temp3[Super] = new Temp3[Sub]("hello");//error val t4: Temp3[Super] = new Temp3[Super]("hello"); //ok val t5: Temp4[Super] = new Temp4[Sub]("hello"); //ok val t6: Temp4[Sub] = new Temp4[Super]("hello"); //error val t7: Temp5[Sub] = new Temp5[Sub]("hello"); //ok val t8: Temp5[Sub] = new Temp5[Super]("hello"); //ok val t9: Temp5[Super] = new Temp5[Sub]("hello"); //error } } //协变 class Temp4[+A](title: String) { //Temp3[+A] //Temp[-A] override def toString: String = { title } } //逆变 class Temp5[-A](title: String) { //Temp3[+A] //Temp[-A] override def toString: String = { title } } //不变 class Temp3[A](title: String) { //Temp3[+A] //Temp[-A] override def toString: String = { title } } //支持协变 class Super //父类 //Sub是Super的子类 class Sub extends Super
标签:this 继承 实例 collect 接口 upper 等等 原来 要求
原文地址:https://www.cnblogs.com/zhanghuicheng/p/10919250.html