Scala包

  • package 包名

    于Java区别:

    1. //嵌套风格
    2. package com{
    3. package atguigu{
    4. package scala{
    5. }
    6. }
    7. }
  1. 一个源文件中可以有多个packge
  2. 子包中的类可以直接访问父包中的内容,无需导包

实例:

  1. package com{
  2. // 在外层包中定义单例对象
  3. object Outer{
  4. var out: String = "out"
  5. def main(args: Array[String]): Unit = {
  6. Inner // 不能在外层调用内层对象
  7. //通过导入包可以访问
  8. import com.atguigu.scala.Inner
  9. println(Inner.in)
  10. }
  11. }
  12. package atguigu{
  13. package scala{
  14. // 内层包中定义单例对象
  15. Object Inner{
  16. val in: String = "in"
  17. def main(args: Array[String]): Unit = {
  18. println(Outer.out) // 访问
  19. Outer.out = "outer" // 更改
  20. }
  21. }
  22. }
  23. }
  24. }
  25. // 在同一文件中定义多个包
  26. package aaa{
  27. package bbb{
  28. import com.atguigu.scala.Inner
  29. object Test{
  30. def main(args: Array[String]): Unit = {
  31. println(Inner.in)
  32. }
  33. }
  34. }
  35. }

包对象

  • 与包同名的对象,定义在包对象中的成员,作为其对应包下所有class和object的共享变量,可以直接访问 ```scala package object chapter{ // 定义当前包共享的属性和方法 val commonValue = “NJU” def commonMethod() = { println(s”我们在${commonValue}学习”) } }

// 在同一个包下可以调用

  1. - 必须在同一层级下调用
  2. <a name="nsa2J"></a>
  3. ### 导包
  4. 1. import可以在顶部使用
  5. 1. 局部导入。作用范围内可以使用
  6. 1. 通配符导入: import java.util._
  7. 1. 给类起名:import java.util.{ArrayList => JL} // 将ArrayList类起别名为JL
  8. 1. 导入相同包的多个类:import java.util.{HashSet, ArrayList}
  9. 1. 屏蔽类:import java.util.{ArrayList => _,_} //导入util下的所有包,不导入ArrayList
  10. Scala中三个默认导入:
  11. 1. import java.lang._
  12. 1. import scala._
  13. 1. import scala.Predef._
  14. <a name="APRqc"></a>
  15. ## 类和对象
  16. <a name="IBmEH"></a>
  17. ### 定义类
  18. **Java中**<br />如果是public的,则必须和文件名一致<br />一般,一个.java有一个public类<br />**Scala**<br />Scala中没有public(默认就是public)<br />一个.scala中可以写多个类<br />**Class没有实现可以不写大括号**<br />**创建对象时如果构造器为空,创建对象时可以不写小括号**<br />val类型必须手动初始化,var类型可以使用_ 指定默认值
  19. ```scala
  20. class Student{
  21. // 定义属性
  22. private var name: String = "alice"
  23. @BeanProperty // 自动创建getter setter...
  24. var age: Int = 18
  25. var sex: String = _ // 默认初始值
  26. }
  27. object Test {
  28. def main(args: Array[String]): Unit = {
  29. // 创建对象
  30. val student = new Student()
  31. // 不能 student.name
  32. println(student.age)
  33. student.sex = "female"
  34. }
  35. }

封装

Scala中的public属性,底层实际为private,并通过get方法和set方法对其进行操作。所以Scala并不推荐将属性设置为private,但由于Java框架都利用反射调用getXXX/setXXX方法,有时候为了兼容,为Scala属性设置getset方法(通过@BeanProperty注解实现)

访问权限

  1. Scala中属性默认访问权限public,但无该关键字
  2. private为私有权限,只在类的内部和伴生对象中可用
  3. protected为受保护权限,Scala中同类子类可以使用,同包无法使用
  4. private[包名] 增加包访问权限,包名下其它类可以使用
  5. private可以在伴生类伴生对象中互相访问,private[this] 伴生类都不能访问 ```scala package chapter

// 定义一个父类 class Person { private var idCard: String = “3322” protected var name: String = “alice” var sex String = “female” private[chapter] var age: Int = 18

def printInfo(): Unit = { println(s”Person: $idCard $name $sex $age”) } }

// 定义一个子类 class Worker extends Person { override def printlnInfo(): Unit = { // println(idCard) 不能访问 name = “bob” age = 25 sex = “male” println(s”Worker: $name $sex $age”) } }

object Test { def main(args: Array[String]): Unit = { val person: Person = new Person() // person.idCard //error // person.name // error println(person.age) println(person.sex) person.printInfo()

  1. val worker: Worker = new Worker()
  2. worker.printInfo()

} }

  1. <a name="dJlFT"></a>
  2. ### 构造器
  3. Scala类构造器包括主构造器和辅助构造器<br />**主构造器**
  4. - 主构造器参数列表直接定义在类名后面,添加了val/var表示直接通过主构造器定义成员变量
  5. - 构造器参数列表可以有默认值
  6. - 创建实例,调用构造器可以指定字段进行初始化
  7. - 整个class中除了字段定义和方法定义的代码都是构造代码
  8. ```scala
  9. class 类名(形参列表) { // 主构造器
  10. // 类体
  11. def this(形参列表) { // 辅助构造器
  12. }
  13. def this(形参列表) { // 辅助构造器可以有多个
  14. }
  15. }
  1. object Test {
  2. Class Person(val name: String = "张三", val age: Int = 23) {
  3. println("调用主构造器")
  4. }
  5. def main(args: Array[String]): Unit = {
  6. val person1 = new Person
  7. val person2 = new Person("李四", 24)
  8. val person3 = new Person(age =30)

说明:

  1. 辅助构造器,函数名称this,可以有多个,编译器通过参数个数及类型区分
  2. 辅助构造方法不能直接创建对象,第一行代码必须直接或间接调用主构造方法
  3. 构造器调用其它另外的构造器,要求被调用的必须提前声明 ```scala object Test { def main(args: Array[String]): Unit = { val student1 = new Student //可以省略括号 输出:1. 主构造方法调用 student1.Student() // 输出:一般方法被调用

    val student2 = new Student1(“alice”) // 1. 2. 被调用 val student3 = new Student1(“Bob”, 18) // 1.2.3.都被调用 } }

class Student1() { // 括号一般省略 var name: String = //默认null var age: Int = // 默认0

println(“1. 主构造方法调用”)

//辅助构造器 def this(name:String) { this() // 直接调用主构造方法 println(“2. 辅助构造方法”) this.name = name println(s”name: $name age: $age”) }

def this(nameL String, age: Int) { this(name) // 间接调用主构造器 println(“3. 辅助构造方法二被调用”) this.age = age println(s”name: $name age: $age”) }

def Student(): Unit = { println(“一般方法被调用”) } }

  1. <a name="MzXDj"></a>
  2. #### 构造器参数
  3. - Scala类的主构造器形参包括三种类型:未用任何修饰、var修饰、val修饰
  4. 1. 未用任何修饰符,这个参数为局部变量
  5. 1. var,作为类的成员属性使用,可以修改
  6. 1. val,作为类只读属性使用,不能更改
  7. ```scala
  8. class Student1 {
  9. var name: String = _ //这里必须是var
  10. var age: Int = _
  11. }
  12. class Student2(var name: String, var age: Int)
  13. // 主构造器参数无修饰符
  14. class Student3(name: String, age: Int)
  15. object Test {
  16. def main(args: Array[String]): Unit = {
  17. // 方式一
  18. val student1 = new Student1
  19. student1.name = "alice"
  20. student1.age = 21
  21. //如果不想这样设置参数,想像下面一样,就得在类中增加辅助构造器
  22. println(s"student1: name = ${student1.name}, age = ${student1.age}")
  23. //方式二
  24. val student2 = new Student2("Bob", 12)
  25. println(s"student2: name = ${student2.name}, age = ${student2.age}")
  26. val student3 = new Student3("xxx",111)
  27. println(s"student3: name = ${student3.name}, age = ${student3.age}")// 这样就不行,name和age不是student3的属性
  28. }
  29. }

主构造器+辅助构造器

  1. class Student4(var name: String, var age: Int) {
  2. var school: String = _
  3. def this(name: String, age: Int, school: String) {
  4. this(name,age)
  5. this.school = school
  6. }
  7. def this(arys: Array[String]) {
  8. this(arys(0), arys(1))
  9. }

apply方法

在Scala中,支持创建对象不写new关键字,对此就要通过伴生对象的apply()方法实现
apply必须在object里

  1. object Test {
  2. // 定义Person类
  3. class Person(var name: String = "", var age: Int = 0) {}
  4. // 定义Person伴生对象
  5. object person {
  6. // 定义apply方法
  7. def apply(name: String, age: Int) = new Person(name,age)
  8. }
  9. def main(args: Array[String]): Unti = {
  10. val p = Person("张三", 23) // 调用apply方法
  11. println(p.name, p.age)
  12. }

定义时间工具类

  1. object ClassDemo {
  2. // 定义工具类
  3. object DateUtils {
  4. // 定义SimpleDateFormat类型对象
  5. var sdf: SimpleDateFormat = null
  6. // 定义date2String方法,用来将日期转化成对应字符串
  7. def date2String(date: Date, template: String) = {
  8. sdf = new SimpleDateFormat(template)
  9. sdf.format(date)
  10. }
  11. // 定义string2Date方法
  12. def string2Date(dataString: String, template: String) = {
  13. sdf = new SimpleDateFormat(template)
  14. sdf.parse(dataString)
  15. }
  16. }
  17. def main(args: Array[String]): Unti = {
  18. println(DateUtils.date2String(new Date(), "HH:mm:ss"))
  19. println(DateUtils.string2Date("1314年5月22日","yyyy年MM月dd日"))
  20. }
  21. }

继承和多态

class/object A类 extends B类 {}

  • 类和单例对象都可以有父类 ```scala class Person { var name = “” def sayHello() = println(“Hello, Scala..”) }

object Student extends Person

def main(args: Array[String]): Unit = { Student.name = “张三” println(Student.name) Student.sayHello() }

  1. - 继承的调用顺序:父类构造器->子类构造器
  2. ```scala
  3. object Test {
  4. def main(args: Array[String]): Unit = {
  5. val student1 = new Student
  6. }
  7. }
  8. class Person {
  9. var name: String = _
  10. var age : Int = _
  11. println("1.父类主构造器")
  12. def this(name: String, age: Int){
  13. this()
  14. println("2. 父类辅助构造器调用")
  15. this.name = name
  16. this.age = age
  17. }
  18. def printlnInfo(): Unit = {
  19. println(s"Person: $name $age")
  20. }
  21. }
  22. class Student(name: String, age: Int) extends Person {
  23. var stdNo: String = _
  24. println("3.子类主构造器")
  25. def this(name: String, age: Int, stdNo: String) {
  26. this(name, age)
  27. println("4. 子类的辅助构造器")
  28. this.stdno = stdNo
  29. }
  30. override def printInfo(): Unit = {
  31. println(s"Person: $name $age $stdNo")
  32. }
  33. }

多态

在Java中 属性是静态绑定的

  1. // Java
  2. class Person{
  3. String name = "person";
  4. public void hello(){
  5. System.out.println("hello person")
  6. }
  7. }
  8. class Worker extends Person{
  9. String name = "worker"
  10. public void hello(){
  11. System.out.println("hello worker")
  12. }
  13. public void hi(){
  14. System.out.println("hi worker")
  15. }
  16. }
  17. public class Test{
  18. public static void main(String[] args){
  19. Person person = new Worker()
  20. person.name // person 静态绑定
  21. person.hello() // hello worker 动态绑定
  22. person.hi() //error
  23. }
  24. }
  • Scala中更加彻底,属性也是动态绑定 ```scala object Test { def main(args: Array[String]): Unit = {
    1. val student: Person = new Student
    println(student.name) // student student.hello() // hello student } }

class Person { var name: String = “person” def hello(): Unit = { println(“hello person”) } }

class Student extend Person { var name: String = “student” override def hello(): Unit = { println(“hello student”) } }

  1. <a name="zFKy7"></a>
  2. ## 抽象类
  3. 如果类中有抽象字段或抽象方法,那么该类就是一个抽象类
  4. - 抽象字段:没有初始化值的变量
  5. - 抽象方法:没有方法体的方法
  6. <a name="T8RQ7"></a>
  7. ### 抽象类属性和抽象方法
  8. <a name="yVatH"></a>
  9. #### 基本语法
  10. 1. 定义抽象类: abstract class Person()
  11. 1. 定义抽象属性:val name: String //只有抽象属性没有初始化
  12. 1. 定义抽象方法:def hello(): String //只声明没有实现
  13. - 只要出现抽象属性和方法必须是抽象类
  14. - 抽象类可以有具体方法
  15. <a name="zZ7Ub"></a>
  16. #### 重写和继承
  17. 1. 如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需要声明为抽象类
  18. 1. 重写非抽象方法需要用override修饰,重写抽象方法可以不加
  19. 1. 子类中调用父类的方法使用super关键字
  20. 1. 子类对抽象属性进行实现,父类抽象属性可以用var修饰
  21. 子类对非抽象属性进行重写,父类非抽象属性只支持val类型,而不支持var,因为var修饰符为可变变量,子类继承之后就可以直接使用,没有必要重写
  22. ```scala
  23. object Test {
  24. def main(args: Array[String]): Unit = {
  25. val student = new Student
  26. student.eat() // person eat student eat
  27. student.sleep() //student sleep
  28. }
  29. }
  30. // 定义抽象类
  31. abstract class Person{
  32. // 非抽象属性
  33. val name: String = "person"
  34. // 抽象属性
  35. var age: Int
  36. // 非抽象方法
  37. def eat(): Unit = {
  38. println("person eat")
  39. }
  40. // 抽象方法
  41. def sleep(): Unit
  42. // 非抽象方法
  43. def eat(): Unit = {
  44. println("person eat")
  45. }
  46. }
  47. class Student extends Person {
  48. var age: Int = 18
  49. def sleep(): Unti = {
  50. println("student sleep")
  51. }
  52. // 重写非抽象属性和方法,如果父类是var的,直接改就行了
  53. override val name: String = "student"
  54. override def eat(): Unit = {
  55. super.eat()
  56. println("student eat")
  57. }
  58. }

isInstanceOf & asInstanceOf

  • isInstanceOf 判断是否为指定类型对象
  • asInstanceOf将对象转换为指定类型 ```scala class Person

class Student extends Person { def sayHello(): Unit = { println(“Hello!”) } }

object Test02 { def main(args: Array[String]): Unit = { val person: Person = new Student if (person.isInstanceOf[Student]) person.asInstanceOf[Student].sayHello() } }

  1. <a name="uEPAi"></a>
  2. ### getClass & classOf
  3. - isInstanceOf只能判断出对象是否为指定类型及其子类的对象,而不能精准的判断出对象就是指定类的对象。如果要求精准的判断出指定数据类型,只能使用一下方法
  4. - getClass可以精准获取对象的类型
  5. - classOf[类名] 可以精准获取数据类型
  6. - 使用==操作符可以直接比较类型
  7. ```scala
  8. class Person2
  9. class Student2 extends Person2 {
  10. def sayHello(): Unit = {
  11. println("Hello!")
  12. }
  13. }
  14. object Test03 {
  15. def main(args: Array[String]): Unit = {
  16. val person: Person2 = new Student2
  17. println(person.isInstanceOf[Person2]) //true
  18. println(person.isInstanceOf[Student2]) // true
  19. println(person.getClass == classOf[Person2]) //false
  20. println(person.getClass == classOf[Student2]) //true
  21. }
  22. }

匿名内部类(抽象类型的子类)

使用场景:

  1. 成员方法只调用一次
  2. 可以作为方法的实际参数传递

如果匿名内部类的主构造器为空,小括号可以不写

  1. object Test {
  2. def main(args: Array[String]): Unit = {
  3. // 1
  4. val person: Person = new Person{
  5. override var name: String = _
  6. override def eat(): Unit = println("person eat1")
  7. }.eat()
  8. println(person.name)
  9. // 2
  10. def show(p:person) = p.eat()
  11. val person2: Person = new Person{ //实际上是多态
  12. override def eat(): Unit = println("person eat2")
  13. }
  14. show(person2)
  15. }
  16. }
  17. // 定义抽象类
  18. abstract class Person {
  19. var name: String
  20. def eat(): Unit
  21. }

单例对象(伴生对象)

Scala语言完全面向对象,所以没有静态操作。但是为了能够和Java交互,就产生了一种特殊的对象来模拟类对象,该对象为单例对象。单例对象与类名一致,类所有静态内容都可以放置在它的半生对象中声明。

  1. 单例对象采用object关键字
  2. 单例对象对应的伴生类名称一样
  3. 单例对象的属性和方法都可以通过伴生对象名(类名)直接调用访问(private也可以) ```scala Object Test { def main(args: Array[String]): Unit = { val student = new Student(“alice”, 18) student.printInfo() } }

// 定义类 class Student(val name: String, val age: Int) { def printInfo() = { println(s”student: name = ${name}, age = $age, school = $Student.school”) } }

// 伴生对象 object Student { val school: String = “atg” }

  1. <a name="Y1xaw"></a>
  2. #### 伴生对象调用构造方法
  3. ```scala
  4. Object Test {
  5. def main(args: Array[String]): Unit = {
  6. val student = Student.newStudent("alice",14)
  7. val student2 = Student.apply("bob",18)
  8. val student2 = Student("bob",18) // apply方法可以省略
  9. student.printInfo()
  10. }
  11. }
  12. // 定义类
  13. class Student private(val name: String, val age: Int) { //构造器私有化
  14. def printInfo() = {
  15. println(s"student: name = ${name}, age = $age, school = $Student.school")
  16. }
  17. }
  18. // 伴生对象
  19. object Student {
  20. val school: String = "atg"
  21. // 定义了一个类的对象实例创建方法,包装好
  22. def newStudent(name: String, age: Int): Student = new Student(name, age)
  23. def apply(name: String, age: Int): Student = new Student(name, age)
  24. }
  • 对于伴生对象中的apply() 调用时可以省略 .apply

    使用继承App特质的方式定义程序主入口

    1. object Test extends App{
    2. println("")
    3. }

    单例设计模式

    ```scala class Student private(val name: String, val age: Int) { //构造器私有化 def printInfo() = { println(s”student: name = ${name}, age = $age, school = $Student.school”) } }

// 饿汉式 object Student { private val student: Student = new Student(“alice”,12) def getInstance(): Student = student }

// 懒汉式 object Student2 { private var student: Student2 = _ def getInstance(): Student2 = { if (student == null) { // 如果没有实例的话,创建一个 student = new Student2(“alice”, 18) } student } }

object Test { def main(args: Array[String]): Unit = { val student1 = Student.getInstance() val student2 = Student.getInstance()

  1. // 引用地址完全一样
  2. println(student1)
  3. println(student2)

} }

  1. <a name="e2p75"></a>
  2. ## 特质(Trait)
  3. Scala语言中,采用特质来代替接口,也就是说多个类具有相同特质时,就可以将这个特质独立出来,采用trait声明<br />Scala中trait可以有抽象属性和方法,**也可以有具体的属性和方法**,一个类可以混入多个特质,类似于Java中的抽象类
  4. ```scala
  5. trait 特质名{
  6. }
  7. class 类名 extends 特质1 with 特质2 // 没有父类
  8. class 类名 extends 父类 with 特质1 with 特质2 // 有父类
  1. object Test {
  2. def main(args: Array[String]): Unit = {
  3. val student = new Student
  4. student.sayHello()
  5. student.study()
  6. student.dating()
  7. }
  8. class Person {
  9. val name: String = "person"
  10. var age: Int = 18
  11. def sayHello(): Unit = {
  12. println("hello from:" + name)
  13. }
  14. }
  15. trait Young{
  16. // 声明抽象和非抽象属性
  17. var age: Int
  18. val name: String = "young"
  19. // 非抽象方法
  20. def play(): Unit = {
  21. println("young people is playing")
  22. }
  23. // 抽象方法
  24. def dating(): Unit
  25. }
  26. class Student extends Person with Young {
  27. // 重写冲突的属性
  28. override val name: String = "student"
  29. def dating(): Unit = println(s"student $name is dating")
  30. def study(): Unit = println(s"student $name is studying")
  31. // 重写父类的方法
  32. override def sayHello(): Unit = {
  33. super.sayHello()
  34. println(s"hello froms: student $name")
  35. }
  36. }

单例对象继承特质

  1. object Test07 {
  2. def main(args: Array[String]): Unit = {
  3. ConsoleLogger.log("Success")
  4. ConsoleLogger.warn("Warning")
  5. }
  6. }
  7. trait Logger {
  8. def log(msg: String)
  9. }
  10. trait Waring {
  11. def warn(msg: String)
  12. }
  13. object ConsoleLogger extends Logger with Waring {
  14. override def log(msg: String) = println(s"Log: $msg" )
  15. override def warn(msg: String): Unit = println(s"Warn: $msg")
  16. }

特质的混入

  1. object Test {
  2. def main(args: Array[String]): Unit = {
  3. val student = new Student
  4. student.study()
  5. student.increase()
  6. // 动态混入:让某个对象临时可以访问某个特质中的成员
  7. val studentWithTalent = new Student with Talent {
  8. override def dancing(): Unit = println("dancing")
  9. override def singing(): Unit = println("singing")
  10. }
  11. studentWithTalen.dancing()
  12. }
  13. }
  14. trait Talent {
  15. def singing(): Unit
  16. def dancing(): Unit
  17. }
  18. // 再定义一个特质
  19. trait Knowledge {
  20. var amount: Int = 0
  21. def increase(): Unit
  22. }
  23. class Student extends Person with Young with Knowledge {
  24. // 重写冲突的属性
  25. override val name: String = "student"
  26. def dating(): Unit = println(s"student $name is dating")
  27. def study(): Unit = println(s"student $name is studying")
  28. // 重写父类的方法
  29. override def sayHello(): Unit = {
  30. super.sayHello()
  31. println(s"hello froms: student $name")
  32. }
  33. override def increase()L Unit = {
  34. amount += 1
  35. println(s"student $name knowledge increase $amount")
  36. }
  37. }

特质叠加

  1. trait Talent{
  2. def dancing(): Unit
  3. def increase(): Unit = println("talent increase")
  4. }
  5. trait Knowledge{
  6. def dancing(): Unit
  7. def increase(): Unit = println("knowledge increase")
  8. }
  9. class Student extend Person with Talent with Knowledge {
  10. override def dancing(): Unit = println("dancing")
  11. override def increase(): Unit = {
  12. super.increase() // konwledge increase
  13. }
  14. }
  • 把最后一个特质中的方法作为调用(从右到左)

    特质和抽象类的区别

  1. 优先使用特质,一个类扩展多个特质是方便的,但只能扩展一个抽象类
  2. 如果需要构造函数,使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行

    特质自身类型

    ```scala object Test { def main(args: Array[String]): Unit = { var user = new Register(“alice”, 12345) user.insert() } }

class User(val name: String, val password: String)

trait UserDao { // 想要拥有User的属性又不想继承User _: User => // 将自身类指定为User 依赖注入

// 向数据库插入数据 def insert(): Unit = { println(s”insert into db: ${this.name}”) } }

// 定义注册用户类 class RegisterUser(name: String, password: String) extends User(name, password) with UserDao {}

  1. <a name="ND1Kp"></a>
  2. ### 使用trait实现适配器模式
  3. 设计模式是前辈们对代码开发经验的总结,用来提高代码可复用性、可维护性、可读性、稳健性、安全性
  4. <a name="sSC5U"></a>
  5. #### 分类:
  6. 1. 创建型:单例模式,工厂方法
  7. 1. 结构型:类、特质之间的关系架构,适配器模式,装饰模式
  8. 1. 行为型:类能够做什么,模板方法模式,职责链模式
  9. <a name="nAjXu"></a>
  10. #### 适配器模式
  11. 当特质中有多个抽象方法,而我们只需要其中的某一个或某几个方法时,不得不将该特质中的所有抽象方法重写,这样很麻烦。我们可以定义一个抽象类去继承该特质,重写特质中的抽象方法,方法体为空。这时候我们需要哪个方法只需要定义类继承抽象类,重写指定方法即可,这个抽象类就叫做适配器类
  12. ```scala
  13. object Test01 {
  14. def main(args: Array[String]): Unit = {
  15. val greenHand = new GreenHand
  16. greenHand.support()
  17. greenHand.schoolchild()
  18. }
  19. }
  20. trait PlayLOL {
  21. def top()
  22. def mid()
  23. def adc()
  24. def support()
  25. def jungle()
  26. def schoolchild()
  27. }
  28. abstract class Play extends PlayLOL {
  29. override def top(): Unit = ???
  30. override def mid(): Unit = ???
  31. override def adc(): Unit = ???
  32. override def support(): Unit = ???
  33. override def jungle(): Unit = ???
  34. override def schoolchild(): Unit
  35. }
  36. class GreenHand extends Play {
  37. override def support() = {
  38. println("support")
  39. }
  40. override def schoolchild() = {
  41. println("schoolchild")
  42. }
  43. }

模板方法

扩展性更强,符合开闭原则

  1. abstract class Template {
  2. // 记录获取时间
  3. def code()
  4. // 具体规则
  5. def getRuntime() = {
  6. val start = System.currentTimeMillis()
  7. code()
  8. val end = System.currentTimeMillis()
  9. end - start
  10. }
  11. }
  12. class ForDemo extends Template {
  13. override def code(): Unit = for(i <- 1 to 10000) println("say hello")
  14. }
  15. def main(args: Array[String]): Unit = {
  16. val fd = new ForDemo
  17. println(fd.getRuntime())
  18. }

样例类

case class 样例类(val/var 成员变量名:类型 …) val/var 如果不写默认是val , 括号不能省
样例类中默认的方法

  • apply() 让我们快速使用类名创建对象,省去new关键字
  • toString() 打印对象属性
  • equals() 可以让我直接用==判断对象成员变量值
  • hasCode() 用来获取对象的哈希值,同一对象哈希值相同
  • copy() 可以快速创建一个属性值相同的实例对象,还可以使用带名参数赋值 ```scala object Test02 { def main(args: Array[String]): Unit = { val p1 = Person(“李四”, 24) // 因为有apply方法所以省略new

    println(p1) // 默认调用类toString方法

    val p2 = Person(“李四”, 24)

    println(p1 == p2) // equals()让我们可以用==比较对象的属性

    // 同一对象哈希值肯定相同,不同对象哈希值一般不同,下面相同 println(p1.hashCode()) println(p2.hashCode())

    // 基于一个对象快速构建另一个对象 val p3 = p2.copy(age = 35) println(p3) } }

case class Person(name: String = “张三”, var age: Int = 23)

  1. ```scala
  2. // 计算器样例
  3. object Test04 {
  4. def main(args: Array[String]): Unit = {
  5. val c = Calculate(3, 2)
  6. println(c.add()) //5
  7. }
  8. }
  9. case class Calculate(a: Int, b: Int) {
  10. def add() = a + b
  11. def subtract() = a - b
  12. def multiply () = a * b
  13. def divide() = a / b
  14. }

样例对象

用case修饰,没有主构造器

  1. 当作枚举值使用:固定值用于统一规范
  2. 作为没有任何参数的消息传递 ```scala object Test03 { def main(args: Array[String]): Unit = { val person = Person03(“张三”, Male) println(person.name, person.sex) //(张三,Male) } }

trait Sex {

}

case object Male extends Sex

case object Female extends Sex

case class Person03(var name: String, var sex: Sex)

  1. <a name="DTIjE"></a>
  2. ### trait构造机制
  3. ```scala
  4. trait Logger {
  5. println("执行Logger构造器")
  6. }
  7. trait MyLogger extends Logger{
  8. println("执行MyLogger构造器")
  9. }
  10. trait TimeLogger extends Logger {
  11. println("执行TimeLogger构造器")
  12. }
  13. class Person {
  14. println("执行Person构造器")
  15. }
  16. class Student extends Person with MyLogger with TimeLogger {
  17. println("执行Student类构造器")
  18. }
  19. def main(args: Array[String]): Unit = {
  20. val student = new Student
  21. /**
  22. 1 执行Person类构造器
  23. 2 执行Logger构造器
  24. 3 执行MyLogger构造器
  25. 4 执行TimeLogger构造器
  26. 5 执行Student类构造器
  27. */
  28. }

案例:程序员类

  1. class Programeer {
  2. var name: String = _
  3. var age: Int = _
  4. def eat() {}
  5. def skill() {}
  6. }
  7. trait BigData {
  8. def learningBigDate() {
  9. println("learnint bigdata")
  10. }
  11. }
  12. class JavaProgrammer extends Programmer {
  13. override eat() {
  14. println("Java eat")
  15. }
  16. override skill() {
  17. println("Java skill")
  18. }
  19. }
  20. class PythonProgrammer extends Programmer {
  21. override eat() {
  22. }
  23. override skill(){
  24. }
  25. }
  26. class PartJavaProgrammer extends JavaProgrammer with BigData {
  27. override eat() {
  28. }
  29. override skill(){
  30. super.skill()
  31. learningBigData()
  32. }
  33. }
  34. class PartPythonProgrammer extends PythonProgrammer with BigData {
  35. override eat() {
  36. }
  37. override skill(){
  38. super.skill()
  39. learningBigData()
  40. }
  41. }
  42. object Test {
  43. def main(args: Array[String]): Unit = {
  44. val jp = new JavaProgrammer
  45. jp.name = "zhangsan"
  46. jp.age = 23
  47. jp.skll()
  48. jp.eat()
  49. val pjp = new PartJavaProgrammer
  50. pjp.name = "666"
  51. pjp.age = 23
  52. pjp.skill()
  53. }
  54. }
  1. Object Test {
  2. def main(args: Array[String]): Unit = {
  3. // 创建二维数组
  4. val array: Array[Array[Int]] = Array.ofDim[Int](2,3)
  5. // 访问元素
  6. array(0)(2) = 19
  7. array(1)(0) = 25
  8. println(array.mkString(", "))
  9. for (i <- 0 until array.length; j <- 0 until array(i).length) {
  10. println(array(i)(j))
  11. }
  12. for ( i <- array.length; j <- array(i).indices) {
  13. print(array(i)(j) + "\t")
  14. if (j == array(i).length -1) println()
  15. }
  16. array.foreach(line => line.foreach(println))
  17. array.foreach(_.foreach(println))
  18. }
  19. }