开发者学堂课程【Scala 核心编程 - 进阶:Scala 下界介绍和应用实例】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/610/detail/9154
Scala 下界介绍和应用实例
内容介绍
一、Java 中下界
二、scala 中下界
三.scala 中下界应用实例
一.Java中下界
在Java 泛型里表示某个类型是A类型的父类型,使用 super 关键字
<T super A>
//或用通配符的形式:
<? super A>
二.scala 中下界
在 scala 的下界或下限,使用 >: 关键字,语法如下:
[T>:A]
//或用通配符:
[__>: A]
三.scala 中下界应用实例
object LowerBoundsDemo{
def main(args: Array[String]): Unit = {
biophony(Seq(new Earth,new Earth)).map(_.sound())
biophony(Seg(new Animal,newAnimal)).map(_.sound
(
)
)
biophony(Seq(new Bird,new Bird)).map(_.sound()
)
val res=biophony(Seq(new Bird))
val res2 =biophonyiSeg(new Object))
val res3=biophony(Seq(newMoon))
println("\nres2="+res2)
printin("\nres3="+res2)
}
def biophony[T>:Animal](things: Seq[T]) = things
}
class Earth{//Earth类
defsound(){//方法
printin("hello!")
class Animal extends Earth{
overridedefsound()={//重写了Earth的方法sound() printin("anhal sound")
}
}
class Bicd extends Animal
override defsound()={//将Animal的方法重写 print("bird sounds")
}
}
class Moon
{}
这里单独写了一个 moon,月球月亮的意思。月亮这个类不跟任何类发生关系,是独立存在的。
现在请看代码,把这个T改成大于等于 animal,things 就不调 sound。animal 有sound,但是不能保证 animal 的父类都有 sound。前面那个子类可以调是因为父类有的方法只要没选持有的,子类就可以调。这里把 things 直接返回去看区别。
调第一个方法:
biophony(Seq(new Earth,new Earth)).map(_.sound())
先用这个方法拿到了集合,进行map,在map里面调sound。Earth是animal的父类,没有问题。
biophony(Seg(new Animal,newAnimal)).map(_.sound)
T>animal,所以第二个也是对的。
biophony(Seq(new Bird,new Bird)).map(_.sound()
这个是传了两只鸟进去,这个bird传过来,这个animal ,bird是他的子类,按理说这地方应该报错,但是实际情况这个也是对的,这个很难理解。
bird传进去,从语法上不能按照上界的思维方式来推。如果传的是animal的子类,他也可以接受,但是他会按照animal的方式,按照他的父类的方式来处理。而且输出的声音,还不是animal叫,而是鸟叫。下面运行一下代码。
新建一个案例
package com.atguigu.chapter18.lowerbounds
那么就有了一个结论:如果是下界,就可以随便传参数。
1)只不过和 Animal 直系的,是 Animal 父类的还是父类处理,是
Animal 子类的按照 Aniinal处理,
2)和 Animal 无关的,一律按照 Object 处理!
object LowerBoundsDemo01 {
def main(args: Array[String]):Unit = {
printin("ok
!
")
//满足下界的约束
biophony(Seq(new Earth,new Earth)).map(_.sound())
//满足下界的约束
biophony(Seq(new A
nimal
,new A
nimal
)).map(_.sound())
biophony(Seg(new Animal,newAnimal)).map(_.sound
(
)
)
//这里我们不能使用上界的思维去推导,这里是可以运行的
biophony(Seq(new B
ird
,new B
ird
)).map(_.sound())
}
//
下
界
def biophony[T
>
:Animal](things: Seq[T]) = things
}
class Earth{//Earth类
defsound(){//方法
printin("hello!")
}
class Animal extends Earth{
overridedefsound()={//重写了Earth的方法sound() printin("anhal sound")
}
}
class Bicd extends Animal
override defsound()={//将Animal的方法重写 print("bird sounds")
}
}
class Moon
{}
运行:
下面再传一段代码:
//把 animal 换成 bird
biophony(Seq(new Bird,new Bird)).map(_.sound())
运行:
下面把moon传进去:
biophony(Seq(new Moon,new Moon))
没有报错。
biophony(Seq(new Bird,new Bird)).map(_.sound())
这儿传了两只鸟进去,发的是鸟叫,不是动物叫。要理解这个的话要去做测试。
如果用这个方法直接输出,他返回的类型实际上是一个animal。也就是说它产生的bird这个对象实例仍然是bird,但是这个引用实际上是被传给了animal,在调这个sound的时候,只是相当于这个方法去覆盖了animal的方法,那这个怎么来看这个情况?
下面这个情况只能在这个地方才能看得到,用scala运行一下看一下效果,来看看是不是他们返回的类型和我们想的是否一样:
class Earth{//Earth类
defsound(){//方法
printin("hello!")
class Animal extends Earth{
overridedefsound()={//重写了Earth的方法sound() printin("anhal sound")
}
}
class Bicd extends Animal
override defsound()={//将Animal的方法重写 print("bird sounds")
}
}
class M
oon
{
//
def
sound
()=(//将Animal的方法重写
//
print(“bird
sounds”)
//
}
}
先把这个方法def biophony[T>:Animal](things: Seq[T]) = things
}粘过来。这是第一个方法,有了这个方法过后再去粘贴这个bird的这个方法粘贴回车。
可以看到它实际上是让一个animal这个类型自行就相当于你有两个bird的,再调上的方法的时候,其实相当于说调这个bird的时候,他还是去找,因为覆盖了animal的方法。再来看第二个,如果传了一个问题,粘贴回车。
那么得出结论:如果传的是跟他没有任何关系的,返回的就是object。那么我们再来看一个这个类型,把biophony(Seq(new Earth,new Earth))粘过来,这时返回的就是earth本身:
如果有方法覆盖,那仍然是调动的子类的。假如bird里面没有sound的方法,可以看一下他调的是什么声音。先保存,为了好看先把它处理掉:
//biophony (seq(new moon))
现在为什么调sound也能成功?因为他其实是按照animal来进行这个继承关系的处理。
传了两个鸟进去,仍然叫sound成功了。这个时候会发出动物的叫声。
以上就是要讲的案例。