Scala面向对象编程学习手册(四)------匿名内部类,Trait

匿名内部类

匿名内部类的本质

  • 一个没有名字的类,自动构建一个类继承抽象类或者接口,实现可以new一个抽象类或者接口

匿名内部类的定义语法

val 变量名称 = new 抽象类/Trait{
	//重写属性或者方法
}

直接new一个抽象类或者Trait的子类,重写方法后将对象赋值给一个变量

匿名内部类的实现

abstract class Person05 {
  //具体的属性
//  var name:String = "itcast"
//  var age:Int = 20
  //抽象的属性
  var name:String
  var age:Int

  //具体的方法
//  def sayHello = println("Hello,Person ~")
  //抽象的方法
  def sayHello
}

//如果多次构建这个类的实例
class Stduent05 extends Person05 {
  override var name: String = "student"
  override var age: Int = 18

  override def sayHello: Unit = println("Hello,Student ~")
}

object TestStudent05{
  def main(args: Array[String]): Unit = {
    //正常通过构建子类的实例,来实现对抽象类的使用
    val student = new Stduent05
    student.sayHello

    //通过匿名内部类实现new 抽象类:一般用于临时的使用一次抽象类或者接口的方法
    val person = new Person05 {
      override var name: String = "heima"
      override var age: Int = 10

      override def sayHello: Unit = println("Hello, Person ~")
    }
    person.sayHello
  }
}

Trait

Trait的定义及使用

Trait的设计及功能

  • Trait的设计类似于Java中Interface的设计,可以当做Java中的Interface来使用,但是比接口的功能更加强大
  • 当Trait当做Interface来使用时,基本与Interface没有区别

Trait的定义语法

  • 关键字:trait

  • 定义

    trait HelloTrait {
    //抽象方法
    def sayHello
    }
    
    trait ByeTrait {
    def sayBye
    }
    

Trait的使用

  • 关键字:extends

    • Scala中类的继承和Trait的实现都使用extends来表示
  • 实现多个关键字:with

    class Person06 extends HelloTrait with ByeTrait with Serializable {
    //实现接口中的抽象方法
    override def sayHello: Unit = println("Hello ~ Person")
    
    override def sayBye: Unit = println("Bye ~ Person")
    }
    
    object Person06{
    def main(args: Array[String]): Unit = {
    val p1 = new Person06
    p1.sayHello
    p1.sayBye
    }
    }
    

Trait实现工具类的封装

  • Trait中的方法定义

    • 抽象方法:只定义方法名,没有方法体,没有实现逻辑
    • 具体方法:定义了方法名和方法体,包含了实现逻辑
    • Trait中既可以定义抽象方法,也可以定义具体方法
  • Trait实现封装工具类

    • 在Trait中定义具体的方法,所有继承了该Trait的类都具有了该方法

      • 构建一个工具类的父类:包含通用的工具方法

实现

//需求:构建一个Trait,实现切分字符串和拼接字符串
trait StringUtilsTrait {
  //可以定义抽象方法和属性,当做接口来实现
  //可以定义具体的方法和属性
  def subStr(str:String,start:Int,len:Int):String = {
    str.substring(start,start+len)
  }

  def concatStr(sep:String,str:String *):String = {
    str.mkString(sep)
  }

}

object TimeUtils extends StringUtilsTrait {}

object URLUtils extends StringUtilsTrait{}

object TestTrait{
  def main(args: Array[String]): Unit = {
    val str1 = "I"
    val str2 = "like"
    val str3 = "learning"
    println(TimeUtils.subStr(str3,0,5))
    println(TimeUtils.concatStr("-",str1,str2,str3))
  }
}

实例混入Trait

实例混入Trait的介绍

  • 实例混入Trait指的是为了解决相同类的不同实例继承不同Trait的问题

  • 在构建同一个类的实例时,可以指定当前实例化的对象继承哪些Trait

  • 正常的trait的继承:定义类的实现继承

    class Person extends Trait
    
    class Person01 extends HelloTrait {
    override def sayHello: Unit = println("Hello Person")
    }
    
    object TestPerson01{
    def main(args: Array[String]): Unit = {
    val p1 = new Person01
    p1.sayHello
    val p2 = new Person01
    p2.sayHello
    }
    }
    
  • 实例混入trait:指的是可以在构建对象的时候来实现继承Trait

 trait Logger {
    def log(msg:String) = println(msg)
  }

  class UserService

  def main(args: Array[String]): Unit = {
    val service = new UserService with Logger
    service.log("混入的方法")
  }

Trait的构造机制及Trait继承Class

Trait的构造器

  • Trait不支持构造参数,但是每个Trait都有一个无参构造器

  • 类中:除了成员属性和成员方法外,其他的所有代码都属于主构造器

    class Person02(var name:String,var age:Int) {
    println("Start ……………………")
    //成员属性
    var country :String = "China"
    
    //成员方法
    def sayHello = println("Hello")
    println("End ……………………")
    
    }
    
    object Person02{
    def main(args: Array[String]): Unit = {
    val itcast = new Person02("itcast",18)
    itcast.sayHello
    }
    }
    

类的基本构造顺序

  • 从左到右依次执行继承的父类或者Trait的构造,再执行自身的构造

继承一个类和两个Trait

class Person02() {
  println("Start Person ……………………")

}

trait HelloTrait1 {
  println("Start HelloTrait ……")
}

trait ByeTrait1 {
  println("Start ByeTrait ……")
}

class Student02 extends Person02 with HelloTrait1  with ByeTrait1 {
  println("Start Student ……………………")
}


object Person02{
  def main(args: Array[String]): Unit = {
    val student = new Student02
  }
}

//输出结果
Start Person ……………………
Start HelloTrait ……
Start ByeTrait ……
Start Student ……………………

复杂继承的构造顺序

  • 如果一个类继承多个Trait,而Trait又继承父Trait,先构造父Trait,再构造子Trait

  • 如果多个子Trait的父Trait相同,则父Trait只构造一次

  • 继承关系
    在这里插入图片描述

    class Student extends Person with MyLogger with TimeLogger1
    Trait MyLogger extends Logger
    Trait TimeLogger extends Logger
    

构造顺序

class Person02() {
  println("Start Person ……………………")

}


trait Logger{
  println("Strat Logger ……")
}
trait MyLogger extends Logger {
  println("Start MyLogger ……")
}

trait TimeLogger extends Logger {
  println("Start TimeLogger ……")
}

class Student02 extends Person02 with MyLogger  with TimeLogger {
  println("Start Student ……………………")
}


object Person02{
  def main(args: Array[String]): Unit = {
    val student = new Student02
  }
}
//输出结果
Start Person ……………………
Strat Logger ……
Start MyLogger ……
Start TimeLogger ……
Start Student ……………………

小结:

  • 基本:从左往右依次构造,最后构造自己
  • 特殊:如果继承的Trait有父Trait,先构造父Trait,再构造子Trait
    • 如果子Trait的父Trait是同一个,父Trait只构造一次
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值