大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值

大数据技术之_16_Scala学习_06

第八章 面向对象编程-高级

8.1 静态属性和静态方法

8.1.1 静态属性-提出问题

8.1.2 基本介绍

8.1.3 伴生对象的快速入门

示例代码如下:

package com.atguigu.chapter08.test

object AccompanyObjectDemo {
   
  def main(args: Array[String]): Unit = {
   
    println(ScalaPerson.sex) // 在底层等价于 ScalaPerson$.MPDULE$.sex()
    ScalaPerson.sayHi() // 在底层等价于 ScalaPerson$.MPDULE$.sayHi()
  }
}

// class ScalaPerson 是伴生类,将非静态的内容写到该类中
// class ScalaPerson 编译后生成 ScalaPerson.class
class ScalaPerson {
   
  var name: String = _
}

// object ScalaPerson 是伴生对象,将静态的内容写到该对象中
// object ScalaPerson 编译后生成 ScalaPerson$.class
// 对于伴生对象的内容,我们可以直接通过 ScalaPerson.属性 或者 ScalaPerson.方法
object ScalaPerson {
   
  var sex: Boolean = true
  def sayHi():Unit = {
   
    println("object ScalaPerson sayHi")
  }
}

输出结果如下:

true
object ScalaPerson sayHi

伴生对象的快速入门源码分析图解

8.1.4 伴生对象的小结

8.1.5 最佳实践-使用伴生对象解决小孩游戏问题

  设计一个 var total Int 表示总人数,我们在创建一个小孩时,就把 total 加1,并且 total 是所有对象共享的就 ok 了。我们使用伴生对象来解决。
示例代码如下:

package com.atguigu.chapter08.test

object ChildGameTest {
   
  def main(args: Array[String]): Unit = {
   
    // 传统的方式
    // 创建很多小孩,加入游戏
    // 定义一个变量 total
    // var total = 0
    // 我们这个 total 没有在一个对象里面,不是面向对象的编程

    // 伴生对象的方式
    val child01 = new Child("白骨精")
    val child02 = new Child("银角大王")
    val child03 = new Child("牛魔王")

    Child.joinGame(child01)
    Child.joinGame(child02)
    Child.joinGame(child03)

    Child.showNum()
  }
}

// 伴生类
class Child(cName: String) {
   
  var name = cName
}

// 伴生对象
object Child {
   
  // 总人数
  var total: Int = 0

  def joinGame(child: Child): Unit = {
   
    printf("%s 小朋友加入游戏\n", child.name)
    total += 1
  }

  def showNum(): Unit = {
   
    printf("当前有 %d 个小朋友在玩游戏\n", total)
  }
}

输出结果如下:

白骨精 小朋友加入游戏
银角大王 小朋友加入游戏
牛魔王 小朋友加入游戏
当前有 3 个小朋友在玩游戏
8.1.6 伴生对象-apply 方法

  在伴生对象中定义 apply 方法,可以实现: 类名(参数) 方式 来创建对象实例。
示例代码如下:

package com.atguigu.chapter08.apply

object ApplayDemo01 {
   
  def main(args: Array[String]): Unit = {
   
    val list = List(1, 2, 3)
    println(list) // List(1, 2, 3)

    // 传统的方式:new 出来
    val p1 = new Pig("小花猪")
    println("p1.name=" + p1.name)

    // 现在的方式
    // 在伴生对象中自定义 apply 方法,可以实现: 类名(参数) 方式 来创建对象实例。
    // 使用 apply 方法来创建对象
    val p2 = Pig("小黑猪") // 自动触发 apply(pName: String)
    val p3 = Pig() // 自动触发 apply()

    println("p2.name=" + p2.name)
    println("p3.name=" + p3.name)
  }
}

// 伴生类
class Pig(pName: String) {
   
  var name: String = pName
}

// 伴生对象
object Pig {
   
  // 编写自定义的 apply 方法
  def apply(pName: String): Pig = new Pig(pName)

  def apply(): Pig = new Pig("默认同名猪猪")
}

输出结果如下:

List(1, 2, 3)
p1.name=小花猪
p2.name=小黑猪
p3.name=默认同名猪猪

8.2 单列对象

  这个部分我们放在【第十七章 scala 设计模式】专题进行讲解。

8.3 接口

8.3.1 回顾 Java 接口

8.3.2 Scala 接口的介绍


trait 原理示意图如下:

8.3.3 trait 的声明


示例代码如下:

package com.atguigu.chapter08.mytrait

object TraitDemo01 {
   
  def main(args: Array[String]): Unit = {
   

  }
}

// 在 scala 中,java 中的所有接口可以当做特质使用。

// Serializable:就是 scala 的一个特质。
// trait Serializable extends Any with java.io.Serializable
object T1 extends Serializable {
   

}

// Cloneable:就是 scala 的一个特质。
// trait Cloneable extends java.lang.Cloneable
object T2 extends Cloneable {
   

}
8.3.4 Scala 中 trait 的使用

8.4 特质 trait

8.4.1 特质的快速入门案例分析

8.4.2 代码完成

示例代码如下:

package com.atguigu.chapter08.mytrait

object TraitDemo02 {
   
  def main(args: Array[String]): Unit = {
   
    val c1 = new C()
    val e1 = new E()
    c1.getConnect()
    e1.getConnect()
    println("----------")
    c1.getConnect("张三", "123456")
    e1.getConnect("李四", "000000")

  }
}

// 按照要求定义一个 trait
trait trait02 {
   
  // 定义一个规范
  // 声明方法,抽象的
  def getConnect()

  def getConnect(user: String, pwd: String): Unit
}

class A {
   }

class B extends A {
   }

class C extends A with trait02 {
   
  override def getConnect(): Unit = {
   
    println("c 连接mysql")
  }

  override def getConnect(user: String, pwd: String): Unit = {
   
    println(user +" 用户连接mysql")
  }
}

class D {
   }

class E extends D with trait02 {
   
  override def getConnect(): Unit = {
   
    println("e 连接oracle")
  }

  def getConnect(user: String, pwd: String): Unit = {
   
    println(user +" 用户连接oracle")
  }
}

class F extends D {
   }

输出结果如下:

c 连接mysql
e 连接oracle
----------
张三 用户连接mysql
李四 用户连接oracle
8.4.3 特质 trait 的再说明

  1、Scala 提供了特质(trait),特质可以同时拥有抽象方法和具体方法,一个类可以实现/继承多个特质。
  2、特质中没有实现的方法就是抽象方法。类通过 extends 继承特质,通过 with 可以继承多个特质。
  3、所有的 java 接口都可以当做 Scala 特质使用。
示例代码如下:

package com.atguigu.chapter08.mytrait

object TraitDemo03 {
   
  def main(args: Array[String]): Unit = {
   
    val s1 = new Sheep
    s1.sayHi()
    s1.sayHello()
  }
}

// 当一个 trait 有抽象方法和非抽象方法时:
// 那么一个 trait 在底层就对应生成两个东东:
// 1、Trait03.class        接口 Trait03
// 2、Trait03$class.class  抽象类 Trait03$class
trait Trait03 {
   
  // 定义规范
  // 抽象方法
  def sayHi()
  // 实现普通方法
  def sayHello(): Unit = {
   
    println("say hello")
  }
}

// 当一个 trait 有 接口 和 抽象类 时:
// class Sheep extends Trait03 在底层对应:
// 1、class Sheep implements Trait03
// 2、当在 Sheep 类中要使用 Trait03 中已实现的方法,就通过 Trait03$class.sayHello()
class Sheep extends Trait03 {
   
  override def sayHi(): Unit = {
   
    println("say hi")
  }
}

输出结果如下:

say hi
say hello

示例代码的底层源码分析图解:

演示一个类继承多个特质的语法:

8.4.4 带有具体实现的特质

  说明:和 Java 中的接口不太一样的是特质中的方法并不一定是抽象的,也可以有非抽象方法(即:实现了的方法)。实现了的方法的术语: 默认实现。提示:在 jdk1.8 中接口也可以有默认实现,就是 scala 的 trait 的带来的特性。
示例代码如下:

package com.atguigu.chapter08.mytrait

/**
  * 带有具体实现的特质
  * 说明:和 Java 中的接口不太一样的是特质中的方法并不一定是抽象的,也可以有非抽象方法(即:实现了的方法)。实现了的方法的术语: 默认实现。
  * 提示:在 jdk1.8 中接口也可以有默认实现,就是 scala 的 trait 的带来的特性。
  */
object TraitDemo04 {
   
  def main(args: Array[String]): Unit = {
   
    val mysql = new MySQL0
    mysql.insert(2)
  }
}

trait Operate0 {
   
  def insert(id: Int): Unit = {
   
    println("保存数据=" + id)
  }
}

trait DB0 extends Operate0 {
   
  override def insert(id: Int): Unit = {
   
    print("向数据库中")
    super.insert(id)
  }
}

class MySQL0 extends DB0 {
   

}

输出结果如下:

向数据库中保存数据=2
8.4.5 带有特质的对象:动态混入(mixin)


示例代码如下:

package com.atguigu.chapter08.mixin

/**
  * 1、除了可以在类声明时继承特质以外,还可以在构建对象时混入特质,扩展目标类的功能。
  * 2、此种方式也可以应用于对抽象类功能进行扩展。
  * 3、动态混入是 Scala 特有的方式(java 没有动态混入),可在不修改类声明/定义的情况下,扩展类的功能,非常的灵活,耦合性低 。
  */
object MixinDemo01 {
   
  def main(args: Array[String]): Unit = {
   
    // 在不修改类的定义的基础上,让该类可以使用 trait 中的方法
    val oracle = new OracleDB1 with Operate1 // 动态混入
    oracle.insert(999)
    val mysql = new MySQL1 with Operate1
    mysql.insert(400)

    // 如果抽象类中有抽象的方法,如何动态混入特质?如下:
    val mysql11 = new MySQL11 with Operate1 {
   
      override def say(
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值