God of spark is Scala---面向对象编程(高级篇)

一. 静态属性和静态方法

1. Scala中静态的概念-伴生对象
  • 基本介绍
    Scala语言是完全面向对象(万物皆对象)的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,我们称之为类的伴生对象。这个类的所有静态内容都可以放置在它的伴生对象中声明和调用。
  • 伴生对象快速入门
// class ScalaPerson是伴生类
class ScalaPerson {
  var name : String = _
}
// object ScalaPerson是伴生对象
object ScalaPerson {
   var sex : Boolean = true
}
  • 伴生对象小结
    1)Scala中伴生对象采用object关键字声明,伴生对象中声明的全是 "静态"内容,可以通过伴生对象名称直接调用。
    2)伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
    3)伴生对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。
    4)从语法角度来讲,所谓的伴生对象其实就是类的静态方法和成员的集合。
    5)从技术角度来讲,scala还是没有生成静态的内容,只不过是将伴生对象生成了一个新的类,实现属性和方法的调用。
    6)从底层原理看,伴生对象实现静态特性是依赖于 public static final MODULE$ 实现的。
    7)伴生对象的声明应该和伴生类的声明在同一个源码文件中(如果不在同一个文件中会运行错误!),但是如果没有伴生类,也就没有所谓的伴生对象了,所以放在哪里就无所谓了。
    8)如果 class A 独立存在,那么A就是一个类, 如果 object A 独立存在,那么A就是一个"静态"性质的对象[即类对象], 在 object A中声明的属性和方法可以通过 A.属性 和 A.方法 来实现调用。
    9)当一个文件中,存在伴生类和伴生对象时,文件的图标会发生变化。
    God of spark is Scala---面向对象编程(高级篇)_第1张图片
2. 伴生对象-apply方法
  • 基本介绍
    在伴生对象中定义apply方法,可以实现: 类名(参数) 方式将来创建对象实例
    God of spark is Scala---面向对象编程(高级篇)_第2张图片

二. 接口

1. Scala接口的介绍

从面向对象来看,接口并不属于面向对象的范畴,Scala是纯面向对象的语言,在Scala中,没有接口。

Scala语言中,采用特质trait(特征)来代替接口的概念,也就是说,多个类具有相同的特征(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。 理解trait 等价于(interface + abstract class)

2. 特质
  • trait的声明
trait 特质名 {
	trait体
}

trait 命名 一般首字母大写.
Cloneable , Serializable

object T1 extends Serializable {  }
Serializable: 就是scala的一个特质。
在scala中,java中的接口可以当做特质使用
3. Scala中使用特质

一个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字连接。

  • 没有父类
class  类名   extends   特质1   with    特质2   with   特质3 ..
  • 有父类
class  类名   extends   父类   with  特质1   with   特质2   with 特质3
4. 叠加特质
  • 基本介绍
    构建对象的同时如果混入多个特质,称之为叠加特质,那么特质声明顺序从左到右,方法执行顺序从右到左。
  • 叠加特质应用案例
trait Operate4 {
  println("Operate4...")
  def insert(id : Int)
}

trait Data4 extends Operate4 {
  println("Data4")
  override  def insert(id : Int): Unit = {
    println("插入数据 = " + id)
  }
}

trait DB4 extends Data4 {
  println("DB4")
  override def insert(id : Int): Unit = {
    print("向数据库")
    super.insert(id)
  }
}

trait File4 extends  Data4 {
  println("File4")
  override def insert(id : Int): Unit = {
    print("向文件")
    super.insert(id)
  }}
class MySQL4 {}

// 1.Scala在叠加特质的时候,会首先从后面的特质开始执行
// 2.Scala中特质中如果调用super,并不是表示调用父特质的方法,而是向前面(左边)继续查找特质,如果找不到,才会去父特质查找
val mysql = new MySQL4 with DB4 with File4
//val mysql = new MySQL4 with File4 with DB4
mysql.insert(888)
  • 叠加特质注意事项和细节
    1)特质声明顺序从左到右。
    2)Scala在执行叠加对象的方法时,会首先从后面的特质(从右向左)开始执行
    3)Scala中特质中如果调用super,并不是表示调用父特质的方法,而是向前面(左边)继续查找特质,如果找不到,才会去父特质查找。
    4)如果想要调用具体特质的方法,可以指定:super[特质].xxx(…).其中的泛型必须是该特质的直接超类类型。
trait File4 extends  Data4 {
  println("File4")
  override def insert(id : Int): Unit = {
    print("向文件")
    super[Data4].insert(id)
}}
5. 富接口
  • 基本定义
    该特质中既有抽象方法,又有非抽象方法
    God of spark is Scala---面向对象编程(高级篇)_第3张图片
6. 特质中的具体字段
  • 基本介绍
    特质中可以定义具体字段,如果初始化了就是具体字段,如果不初始化就是抽象字段。混入该特质的类就具有了该字段,字段不是继承,而是直接加入类,成为自己的字段。
trait Operate6 {
  var opertype : String
  def insert()
}

trait DB6 extends  Operate6 {
  var opertype : String = "insert"
  def insert(): Unit = {
  }
}
class MySQL6 {}

var mysql = new MySQL6 with DB6
//通过反编译,可以看到 opertype
println(mysql.opertype)

三. 特质构造的顺序

  • 介绍
    特质也是有构造器的,构造器中的内容由“字段的初始化”和一些其他语句构成。具体实现请参考“特质叠加”

  • 第一种特质构造顺序(声明类的同时混入特质)
    1)调用当前类的超类构造器
    2)第一个特质的父特质构造器
    3)第一个特质构造器
    4)第二个特质构造器的父特质构造器, 如果已经执行过, 就不再执行
    5)第二个特质构造器
    6)…重复4,5的步骤(如果有第3个,第4个特质)
    7)当前类构造器
    God of spark is Scala---面向对象编程(高级篇)_第4张图片God of spark is Scala---面向对象编程(高级篇)_第5张图片

  • 第2种特质构造顺序(在构建对象时,动态混入特质)
    1)调用当前类的超类构造器
    2)当前类构造器
    3)第一个特质构造器的父特质构造器
    4)第一个特质构造器.
    5)第二个特质构造器的父特质构造器, 如果已经执行过,就不再执行
    6)第二个特质构造器
    7)…重复5,6的步骤(如果有第3个,第4个特质)
    8)当前类构造器

  • 分析两种方式对构造顺序的影响
    1)第1种方式实际是构建类对象, 在混入特质时,该对象还没有创建
    2)第2种方式实际是构造匿名子类,可以理解成在混入特质时,对象已经创建了

四. 嵌套类

1. Scala嵌套类的使用1

请编写程序,定义Scala 的成员内部类和静态内部类,并创建相应的对象实例。

class ScalaOuterClass {
  class ScalaInnerClass { //成员内部类
  }
}
object ScalaOuterClass {  //伴生对象
  class ScalaStaticInnerClass { //静态内部类
  }
}
 val outer1 : ScalaOuterClass = new ScalaOuterClass();
 val outer2 : ScalaOuterClass = new ScalaOuterClass();

 // Scala创建内部类的方式和Java不一样,将new关键字放置在前,使用  对象.内部类  的方式创建
 val inner1 = new outer1.ScalaInnerClass()
 val inner2 = new outer2.ScalaInnerClass()
 //创建静态内部类对象
 val staticInner = new ScalaOuterClass.ScalaStaticInnerClass()
 println(staticInner)
Scala嵌套类的使用2

请编写程序,在内部类中访问外部类的属性。

  • 方式1
    内部类如果想要访问外部类的属性,可以通过外部类对象访问。即:访问方式:外部类名.this.属性名
    God of spark is Scala---面向对象编程(高级篇)_第6张图片
    God of spark is Scala---面向对象编程(高级篇)_第7张图片
  • 方式二
    内部类如果想要访问外部类的属性,也可以通过外部类别名访问(推荐)。 即:访问方式:外部类名别名.属性名 【外部类名.this 等价 外部类名别名】
    God of spark is Scala---面向对象编程(高级篇)_第8张图片
    God of spark is Scala---面向对象编程(高级篇)_第9张图片

你可能感兴趣的:(Scala,编程语言)