trait简介
在scala中并没有提供java语言的interface关键字来定义接口,而是可以使用trait实现多重继承,继承的时候使用extends和with关键字。
/*定义三个trait*/
trait TraitDemo01 {
// 抽象方法定义
def say(content:String):Unit
}
trait TraitDemo02{
//抽象方法定义
def sayHello(content:String):Unit
}
trait TraitDemo03{
//抽象方法定义
def sayGoodBye(content:String):Unit
}
//trait 作为接口使用 那么必须实现trait的抽象方法
class TraitDemo04 extends TraitDemo01 with TraitDemo02 with TraitDemo03 {
// 类实现trait的抽象方法 可以省略 override关键字
override def say(content: String): Unit = {
println(content)
}
override def sayHello(content: String): Unit = {
println(content)
}
override def sayGoodBye(content: String): Unit = {
println(content)
}
}
object Application05{
def main(args: Array[String]): Unit = {
val t1=new TraitDemo04
t1.say("say everything !")
t1.sayHello("say hello!")
t1.sayGoodBye("say GoodBye!")
}
}
trait中定义方法和字段
1)trait中除了能够定义抽象的字段和抽象方法外,还能定义非抽象的字段和方法
2)和抽象类的唯一区别就是抽象类是单继承,而trait是多实现。
实例对象中混入trait
实例对象混入 trait 那么这个实例对象就拥有了trait的所有非私有方法。
/*实例对象中混入trait*/
trait TraitDemo05 {
def say() = {
println("say hello !")
}
}
/*一个类继承了父类或者trait,那么这个类拥有该类或者trait的所有非私有的方法*/
class Baby(var name: String, var age: Int) {
}
object Application005 {
def main(args: Array[String]): Unit = {
val b1 = new Baby("xiaoming", 25)
//为实例对象混入 trait 那么这个实例对象就拥有了trait的所有非私有方法
val b2 = new Baby("xiaohua", 26) with TraitDemo05
b2.say()
}
}
继承trait的构造构造机制
trait TraitDemos {
println("这是TraitDemo03 的主代码块!")
}
trait TraitDemos01 extends TraitDemos {
println("这是TraitDemo04 的主代码块!")
}
trait TraitDemos02 extends TraitDemos{
println("这是TraitDemo05 的主代码块!")
}
class Persons01{
println("这个Person01的 主代码块!")
}
class Students01 extends Persons01 with TraitDemos01 with TraitDemos02{
println("这是 Students01的主代码块 !")
}
object Students01{
def main(args: Array[String]): Unit = {
/**子类继承了(类和trait)的构造机制如下
* 1、执行父类的构造代码块
* 2、执行trait的构造代码块,如果是多个trait那么从左到右执行trait的代码块
* 如果多个trait继承了同一个trait那么先执行父trait的构造代码,然后执行子trait的构造代码
* 父trait的构造代码只执行一次
* 3、 最后执行自己的构造代码,即:子类的构造代码块最后执行*/
val s1=new Students01
}
}
泛型
在创建类和方法的时候可以指定类和方法的泛型。
泛型类
class FanXing[T1,T2,T3](var name:T1) {
def say(): Unit ={
println(name)
}
var age:T2=_
var sex:T3=_
}
object FanXing{
def main(args: Array[String]): Unit = {
val s=new FanXing[String,Int,String]("ysj")
s.say()
s.age=18
s.sex="man"
println("name="+s.name+" "+"age="+s.age+" "+"sex"+s.sex)
}
}
泛型函数
/*泛型方法*/
class FanXingFunction {
def say[T1, T2, T3](name: T1, age: T2): T3 = {
(name + "=" + age).asInstanceOf[T3]
}
}
object FanXingFunction {
def main(args: Array[String]): Unit = {
val f = new FanXingFunction
var result = f.say[String, Int, String]("xiaoming", 25)
println(result)
}
}
泛型类的上边界
class Persons03
class Teacher03 extends Persons03
class Student03 extends Persons03
class Animal03
class Dog03 extends Animal03
class Cat03 extends Animal03
/*上边界 <: 即泛型T只能是 Person03或Person03的子类*/
class FanXingUpBound[T <: Persons03] {
def say(content:T) ={
println(content.getClass)
}
}
object FanXingUpBound{
def main(args: Array[String]): Unit = {
val f1=new FanXingUpBound[Persons03]
val t1=new Teacher03
val s1=new Student03
f1.say(t1)
f1.say(s1)
val f2=new FanXingUpBound[Teacher03]
f2.say(t1)
val f3=new FanXingUpBound[Student03]
f3.say(s1)
/*以下代码错误 因为animal不属于Person03或其子类 不能作为FanXingUpBound的泛型*/
// val animal=new FanXingUpBound[Animal03]
}
}
泛型类的下边界
class Master
class Professor extends Master
class Teacher extends Professor
/*下边界 >: 即T只能是Professor及其Professor的父类*/
class FanXingDownBound[T >: Professor] {
def say(content: T): Unit = {
println(content.getClass)
}
}
object FanXingDownBound {
def main(args: Array[String]): Unit = {
// Master 可以作为FanXingDownBound泛型 以为Master是Professor的父类
val f1 = new FanXingDownBound[Master]
// Professor也可以作为FanXingDownBound泛型 因为Professor就是要求我们传入的泛型
val f2 = new FanXingDownBound[Professor]
//Teacher 不能作为FanXingDownBound泛型 因为Teacher 不是Professor以及Professor的父类
val f3 = new FanXingDownBound[Teacher]
}
}
泛型协变
1)斜变在scala中是一种特色的功能,他完美的解决了java泛型的缺陷。
2)比如 Professor是Master的子类 那么 Card[Professor] 是不是 card[Master]的子类呢? java是无法实现的但是scala的协变解决了此问题。
3)scala协变是泛型类上边界的加强版
class Master05
class Professor05 extends Master05
class Teacher05
/*这个是协变 Professor是Master的子类 那么Card[Professor] 也是Card[Master] 的子类*/
class Card[+T]
class FanXingXieBian {
def say(card: Card[Master05]): Unit = {
println("只要Master级别 以及下一级别的才能入场!")
}
}
object FanXingXieBian{
def main(args: Array[String]): Unit = {
val cm=new Card[Master05]
val cp=new Card[Professor05]
val ct=new Card[Teacher05]
val fx=new FanXingXieBian
fx.say(cm)
fx.say(cp)
// fx.say(ct) 编译报错
}
}
泛型逆变
1)逆变在scala中也是一种特色的功能,他完美的解决了java泛型的缺陷。
2)比如 Professor是Master的子类 那么 Card[Professor] 是不是 card[Master]的子类呢? java是无法实现的但是scala的逆变解决了此问题。
3)scala逆变是泛型类下边界的加强版
class Master06
class Professor06 extends Master06
class Teacher06 extends Professor06
/*这个是逆变 Professor是Master的子类 那么Card[Professor] 也是Card[Master] 的子类*/
class Card[-T]
class FanXingNiBian {
def say(card: Card[Professor06]): Unit = {
println("只要Professor06级别 以及上一级别的才能入场!")
}
}
object FanXingNiBian{
def main(args: Array[String]): Unit = {
val cm=new Card[Master06]
val cp=new Card[Professor06]
val ct=new Card[Teacher06]
val fx=new FanXingNiBian
fx.say(cm)
fx.say(cp)
// fx.say(ct) 编译报错
}
}