一、java接口
只要没有implement接口就没有实现。
package com.atguigu.bigdata.scala.chapter06;
public class Test {
public static void main(String[] args) {
CCC ccc = new BBB(); //为什么BBB没有实现接口CCC却能用?子类包含父类AAA所有内容
System.out.println(BBB.class.getInterfaces().length); //0
System.out.println(AAA.class.getInterfaces().length); //1
}
}
interface CCC {
}
class AAA implements CCC{
}
class BBB extends AAA{
}
二、scala特质trait
1.如果一个对象符合某个特质,那么可以将这个特质“混入”到对象中
2.特质中可以声明属性和方法
3.如果类没有父类可以使用extends关键字混入(类似java抽象类)
4.如果有父类,使用with关键字混入特质
5.动态混入:创建对象的同时混入特质
package com.atguigu.bigdata.scala.chapter06
object Scala04_Field {
def main(args: Array[String]): Unit = {
val user = new User14()
user.test()
//动态混入
val user1444 = new User14444() with MyTrait14
user1444.test()
}
}
trait MyTrait14{
//特质中可以声明属性和方法
//功能
def test() : Unit = {
println("test trait")
}
}
//混入
class User14 extends MyTrait14 {
}
class Parent14 {
}
//如果有父类,使用with关键字混入特质
class User144 extends Parent14 with MyTrait14{
}
class User14444 {
}
三、特质中的抽象方法和属性
- 实现特质,必须重写特质中的抽象方法
2.实现特质,必须重写特质中的抽象属性并初始化
3.特质的完整属性可以重写也可以不重写
可以对比抽象类。
package com.atguigu.bigdata.scala.chapter06
object Scala04_Field {
def main(args: Array[String]): Unit = {
}
}
trait MyTrait15 {
//抽象方法: 只声明,不初始化
def test() : Unit
def test1() : Unit = {
}
//抽象属性
val name : String
//完整属性
val age : Int = 20
}
class User15 extends MyTrait15 {
//实现特质,必须重写特质中的抽象方法
override def test(): Unit = {
}
//实现特质,必须重写特质中的抽象属性并初始化
override val name: String = "张三"
//特质的完整属性可以重写也可以不重写
override val age: Int = 30
}
四、特质、类之间的关系
- 特质可以混入其他特质
2.特质可以继承其他类
3.类可以混入多个特质,使用with关键字
package com.atguigu.bigdata.scala.chapter06
object Scala04_Field {
def main(args: Array[String]): Unit = {
}
}
//特质可以继承其他类
trait MyTrait16 extends User166{
}
//特质可以混入其他特质
trait MyTrait166 extends MyTrait16{
}
trait Mytrait1666{
}
//类可以混入多个特质,使用with关键字
class User16 extends MyTrait16 with MyTrait166 with Mytrait1666 {
}
class User166 {
}
五、trait的初始化顺序
1.如果类存在父类,先初始化父类
2.父类初始化完成后,如果类存在多个特质,会从左到右初始化
3.特质只会初始化一次,所以如果之前初始化了,就不再初始化了。
package com.atguigu.bigdata.scala.chapter06
object Scala04_Field {
def main(args: Array[String]): Unit = {
val user17 = new User177()
}
}
trait MyTrait17 {
println("MyTrait17")
}
trait MyTrait177 {
println("MyTrait177")
}
trait MyTrait1777 {
println("MyTrait1777")
}
class User17 extends MyTrait17 {
println("user17....")
}
class User177 extends User17 with MyTrait17 with MyTrait177 with MyTrait1777 {
println("user177....")
}
打印:
MyTrait17
user17....
MyTrait177
MyTrait1777
user177....
1)执行子类User177
2)执行父类User17
3)执行(构建)父类User17的特质MyTrait17
4)执行特质MyTrait17打印MyTrait17
5)执行父类User17的类体,打印user17....
6)执行with MyTrait17,打印MyTrait177
7)执行with MyTrait1777,打印MyTrait1777
8)执行子类User177类体,打印user177....
注意:子类继承父类,并没有实现父类实现的特质(如上述class User17 extends MyTrait17,那么为什么class User177 extends User17 with MyTrait17没有打两遍MyTrait17呢?原因是父类构造的时候已经初始化trait MyTrait17一次了,所以在子类再with MyTrait17时,不再对trait MyTrait17初始化了。
六、trait的执行顺序
1.特质初始化顺序从左至右,执行顺序从右到左
2.此处的super不是父特质的概念,而是上一个特质的概念,如下LogFile的上一个特质是DB
package com.atguigu.bigdata.scala.chapter06
object Scala04_Field {
def main(args: Array[String]): Unit = {
val mysql = new Mysql()
mysql.insert()
}
}
trait Operate {
def insert() : Unit = {
println("插入数据")
}
}
trait DB extends Operate {
override def insert(): Unit = {
print("向数据库表中 ")
super.insert()
}
}
trait LogFile extends Operate {
override def insert(): Unit = {
print("向日志文件中 ")
//此处的super不是父特质的概念,而是上一个特质的概念,如下LogFile的上一个特质是DB
super.insert()
}
}
//特质初始化顺序从左至右,执行顺序从右到左
class Mysql extends DB with LogFile {
}
打印:向日志文件中 向数据库表中 插入数据