第一章.面向对象

1.Scala包

  1. package com.atguigu.chapter06
  2. object $01_Package {
  3. /**
  4. * 包的好处:1.便于区分同名类 2.便于管理
  5. * java中对于包的用法:
  6. * 1.导包:导包的位置必须在package声明之后,类名之前
  7. * 2.导入包下某个类: import 包名.类名
  8. * 3.导入包下所有类: import 包名.*
  9. * 4.声明包: 语法 package 包名 声明包必须在源文件第一行
  10. * scala中对于包的用法
  11. * 1.导包:scala可以在任意位置导入包
  12. * a.导入包下某个类: import 包名.类名
  13. * b.导入包下所有类: import 包名._
  14. * c.导入包下多个类: import 包名.{类名1,类名2,....}
  15. * d.导入包下某个类,并起别名: import 包名.{类名=>别名}
  16. * e.导入包下除开某个类的所有类: import 包名.{类名=>_ , _}
  17. * 2.声明包
  18. * a.语法: package 包名
  19. * b.声明包必须在源文件第一行
  20. * 3.创建包
  21. * a.语法: package 包名{....}
  22. * b.此种方式创建的包只能在classes目录才能看到
  23. * 4.包对象
  24. * a.语法: package object 包名{...}
  25. * b.包对象定义的非private的属性和方法可以在包中任何位置使用
  26. * 5.包与访问修饰符结合
  27. * a.语法: private[包名] val 属性名:类型 = 值
  28. * b.private[包名]修饰的成员只能在指定的包下使用,其他包不能使用
  29. */
  30. private[chapter06] val sex = "man" //包与访问修饰符结合
  31. import java.util.{HashMap => JavaHashMap} //导入包下所有类
  32. class Person
  33. def main(args: Array[String]): Unit = {
  34. val map = new JavaHashMap[String, Int]()
  35. val p = new xx.Person
  36. }
  37. }
  38. package xx{
  39. class Person
  40. }

2.定义Class

  1. package com.atguigu.chapter06
  2. object $02_ClassDefined {
  3. /**
  4. * java创建类:[访问修饰符] class 类名{....}
  5. * java创建对象: new 类名(....)
  6. *
  7. * scala创建类: class 类名{......}
  8. * scala创建对象: new 类名(.......)
  9. */
  10. class Person{}
  11. def main(args: Array[String]): Unit = {
  12. val person = new Person
  13. println(person)
  14. }
  15. }

3.定义属性和方法

  1. package com.atguigu.chapter06
  2. object $03_ClassFieldAndMethod {
  3. /**
  4. * java中class定义属性:[访问修饰符] 类型 属性名 = 值
  5. * java中class定义方法: [访问修饰符] 返回值类型 方法名(参数类型 参数名,...){...}
  6. * scala中class定义属性: [访问修饰符] val/var 属性名:类型 = 值
  7. * scala中默认是public效果
  8. * scala在class中定义属性的时候var修饰的属性可以通过_赋予初始值
  9. * scala中class定义方法: [访问修饰符] def 方法名(参数名:类型,...):返回值类型 = {....}
  10. *
  11. */
  12. class Person{
  13. //定义属性
  14. val name:String = "zhangsan"
  15. //scala在class中定义属性的时候var修饰的属性可以通过_赋予初始值
  16. var age:String = _
  17. val func = (x:Int,y:Int) => x + y
  18. private val address = "shenzhen"
  19. private def add(x:Int,y:Int) = x + y
  20. }
  21. def main(args: Array[String]): Unit = {
  22. val person = new Person
  23. println(person.name)
  24. println(person.age)
  25. println(person.func(10, 20))
  26. //println(person.address)
  27. //println(person.add(10, 20))
  28. }
  29. }

4.构造器

  1. package com.atguigu.chapter06
  2. object $04_Contruct {
  3. /**
  4. * java中构造器的定义
  5. * 1.定义位置: 定义在类内部
  6. * 2.语法: 访问修饰符 类名(参数类型 参数名,...){...}
  7. *
  8. * scala中构造器分为两种
  9. * a.主构造器
  10. * 1.定义位置: 定义在类名后面
  11. * 2.语法: class 类名([访问修饰符] [val/var] 属性名:类型 [=默认值],....)
  12. * 主构造器使用val/var修饰的属性与不使用val/var修饰的属性属性的区别
  13. * 使用val/var修饰的非private属性可以在class内部/外部都可以使用
  14. * 不使用val/var修饰的属性只能在class内部使用
  15. *
  16. * b.辅助构造器
  17. * 1.定义位置: 定义在class内部
  18. * 2.语法: def this(参数名:类型){
  19. * //辅助构造器第一行必须调用其他的辅助构造器或者主构造器
  20. * this(...)
  21. * }
  22. */
  23. class Person(private val name:String = "zhangsan",var age:Int = 20,address:String){
  24. var money:Double = _
  25. var flag:Boolean = _
  26. def this(flag:Boolean){
  27. this(address="beijing")
  28. this.flag = flag
  29. }
  30. def this(money:Double){
  31. this(true)
  32. this.money=money
  33. }
  34. }
  35. def main(args: Array[String]): Unit = {
  36. val person = new Person(address = "beijing")
  37. //println(person.name)
  38. println(person.age)
  39. //println(person.address)
  40. val person1 = new Person(10.0)
  41. println(person1.flag)
  42. println(person1.money)
  43. val person2 = new Person(false)
  44. println(person2.flag)
  45. }
  46. }

5.封装

  1. package com.atguigu.chapter06
  2. import com.alibaba.fastjson.JSON
  3. import com.alibaba.fastjson.serializer.SerializeFilter
  4. import scala.beans.BeanProperty
  5. object $05_Private {
  6. class Person{
  7. @BeanProperty
  8. var name:String = _
  9. @BeanProperty
  10. var age:Int = _
  11. /*def setName(name:String) = this.name =name
  12. def setAge(age:Int) = this.age =age
  13. def getName()= this.name
  14. def getAge()= this.age*/
  15. /**
  16. * java很多Api底层都需要set/get方法,scala为了兼容java的Api,提供了一个注解@BeanProperty,该注解能够自动生成set/get方法
  17. * @BeanProperty注解不能用于private修饰的属性上
  18. *
  19. */
  20. }
  21. def main(args: Array[String]): Unit = {
  22. val person = new Person
  23. /*person.name="lisi"
  24. person.age=20
  25. println(person.name)*/
  26. person.setName("zhaoliu")
  27. person.setAge(18)
  28. println(person.getName())
  29. //对象转json
  30. val json = JSON.toJSONString(person, null.asInstanceOf[Array[SerializeFilter]])
  31. println(json)
  32. }
  33. }

6.继承

  1. package com.atguigu.chapter06
  2. import scala.util.Random
  3. object $06_Extends {
  4. /**
  5. * java通过extends关键字实现继承
  6. * java通过@overwrite注解实现方法的重写
  7. *
  8. * scala通过extends关键字实现继承
  9. * 哪些不能被继承
  10. * final修饰的class不能被继承
  11. * 父类中private修饰的成员不能被继承
  12. * scala子类可以通过override关键字实现方法实现方法与val属性的重写
  13. * var修饰的属性不能被重写
  14. * scala子类中可以通过super关键字调用父类的方法和属性
  15. * scala中的属性和方法都能做到多态,java只能方法多态
  16. */
  17. class Person{
  18. private val name = "lisi"
  19. var age:Int = _
  20. val address:String = "shenzhen"
  21. def add(x:Int,y:Int) = x+y
  22. }
  23. class Student extends Person{
  24. //override var age:Int =0
  25. override val address:String="beijing"
  26. override def add(x:Int,y:Int):Int={
  27. x*y
  28. }
  29. }
  30. class Student2 extends Person{
  31. override val address:String="tianjin"
  32. override def add(x: Int, y: Int): Int = x-y
  33. }
  34. def main(args: Array[String]): Unit = {
  35. val student = new Student
  36. println(student.age)
  37. println(student.address)
  38. println(student.add(10, 20))
  39. val person = getPerson()
  40. println(person.add(20, 10))
  41. val p:Person = new Student
  42. println(p.address)
  43. }
  44. def getPerson():Person={
  45. val index = Random.nextInt(10)
  46. if(index % 2 ==0) new Student
  47. else new Student2
  48. }
  49. }

7.抽象类

  1. package com.atguigu.chapter06
  2. object $07_Abstract {
  3. abstract class Animal{
  4. //具体属性
  5. val name:String ="lisi"
  6. //抽象属性
  7. val age:Int
  8. //具体方法
  9. def add(x:Int,y:Int):Int=x+y
  10. //抽象方法
  11. def m1(x:Int,y:Int):Int
  12. }
  13. class Dog extends Animal{
  14. override val age:Int = 20
  15. override def m1(x:Int,y:Int):Int = x-y
  16. }
  17. /**
  18. * java中抽象类的定义: abstract class 类名{...}
  19. *
  20. * scala中抽象类的定义: abstract class 类名{....}
  21. * 抽象方法: 没有方法体的方法称之为抽象方法
  22. * 抽象属性: 没有初始化的属性称之为抽象属性
  23. *
  24. * scala抽象类中既可以定义抽象属性也可以定义具体属性,既可以定义抽象方法也可以定义具体方法
  25. *
  26. */
  27. def main(args: Array[String]): Unit = {
  28. val dog = new Dog
  29. println(dog.age)
  30. println(dog.m1(10, 20))
  31. //匿名子类
  32. val animal = new Animal {
  33. override val age: Int = 100
  34. override def m1(x: Int, y: Int): Int = x+y
  35. }
  36. println(animal.age)
  37. }
  38. }

8.单例对象(伴生对象)

Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有“静态”内容都可以放置在它的伴生对象中声明。

  1. package com.atguigu.chapter06
  2. object $08_Object {
  3. /**
  4. * 单例对象: object object名称{....}
  5. * object中定义的所有属性和方法都是类似java static修饰的,可以通过 object名称.属性名/方法名 调用
  6. * class中定义的所有属性和方法都是类似java 非static修饰的
  7. *
  8. * 伴生类[class]和伴生对象[object]
  9. * 必须满足两个条件
  10. * a.class与object的名称必须一致
  11. * b.class与object必须在同一个.scala源文件中
  12. * 伴生类和伴生对象的特性:可以互相访问对方private修饰的成员
  13. * apply方法[主要是为了简化伴生类对象的创建]
  14. * 定义位置: 必须定义在伴生对象中
  15. * 定义apply方法之后,就可以通过 object名称.apply(...)/object名称(...) 获取伴生类的对象
  16. */
  17. def main(args: Array[String]): Unit = {
  18. println($08_Object)
  19. Person.xx()
  20. new Person().yy()
  21. println(Person.getAge())
  22. val person = Person.apply("beijing")
  23. person.yy()
  24. val person2 = Person("tianjin")
  25. println(person2.getName())
  26. }
  27. }
  28. class Person(val address:String){
  29. def this(){
  30. this("")
  31. }
  32. private val age =20
  33. def yy()=println("++++++++++++++++++")
  34. def getName()= Person.name
  35. }
  36. object Person{
  37. private val name ="lisi"
  38. def xx()= println(".............")
  39. def getAge()= new Person().age
  40. def apply(address:String):Person = new Person(address)
  41. def apply():Person = new Person()
  42. }

9.特质

  1. Scala语言中,采用特质trait(特征)来代替接口的概念,也就是说,多个类具有相同的特征(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。
  2. Scala中的trait中即可以有抽象属性和方法,也可以有具体的属性和方法一个类可以混入(mixin)多个特质
  3. Scala引入trait特征,第一可以替代Java的接口,第二个也是对单继承机制的一种补充。
  1. package com.atguigu.chapter06
  2. object $09_TraitDefined {
  3. /**
  4. * scala是单继承多实现
  5. * 特质的语法:trait 特质名{....}
  6. * scala中子类实现特质:
  7. * 1.子类不需要继承父Class,此时子类实现第一个trait使用extends关键字,其他trait的实现使用with关键字
  8. * 2.子类需要继承父class,此时子类实现trait使用with关键字
  9. * 特质中既可以定义具体方法也可以定义抽象方法,既可以定义抽象属性也可以定义具体属性
  10. *
  11. *
  12. */
  13. trait Log1{
  14. //抽象属性
  15. val name:String
  16. //具体属性
  17. val age = 20
  18. //抽象方法
  19. def m1(x:Int,y:Int):Int
  20. //具体方法
  21. def m2(x:Int) = x*x
  22. }
  23. trait Log2
  24. trait Log3
  25. //子类不需要继承父class,此时子类实现第一个trait使用extends关键字,其他trait的实现使用with关键字
  26. class Errorlog extends Log1 with Log2 with Log3{
  27. override val name:String ="lisi"
  28. override def m1(x: Int, y: Int): Int = x + y
  29. }
  30. class ParentLog
  31. //子类需要继承父class,此时子类实现trait使用with关键字
  32. class WarnLog extends ParentLog with Log1 with Log2 with Log3{
  33. override val name: String = "zhangsan"
  34. override def m1(x: Int, y: Int): Int = x - y
  35. }
  36. def main(args: Array[String]): Unit = {
  37. val log = new Errorlog
  38. println(log.name)
  39. println(log.m1(10, 20))
  40. }
  41. }

10.特质混入

  1. package com.atguigu.chapter06
  2. object $10_ObjectMix {
  3. /**
  4. * 对象混入:让某个对象拥有指定特质的属性和方法
  5. * 语法: new 类名(...) with 特质名
  6. */
  7. trait Log{
  8. val name = "lisi2"
  9. }
  10. class ErrorLog
  11. def main(args: Array[String]): Unit = {
  12. val log = new ErrorLog
  13. //println(log.name)
  14. val log2 = new ErrorLog with Log
  15. println(log2.name)
  16. }
  17. }

11.特质的叠加

  1. package com.atguigu.chapter06
  2. object $11_TriatAdd {
  3. /**
  4. * 子类可以实现多个父特质,如果这多个父特质都有一个同名方法并且参数列表也一样的时候,此时子类默认调用该同名方法会报错
  5. * 子类可以通过重写该同名方法来解决报错问题
  6. * 子类中如果想要调用父类的同名方法可以使用super.方法名的方式调用,此时默认情况下调用的是继承顺序最后一个特质的同名方法
  7. * 如果子类想要调用指定父特质的同名方法可以使用super[特质名].方法名的方式调用
  8. * 子类可以实现多个父特质,如果这多个父特质中都有一个同名方法并且参数列表也一样的时候,并且这多个特质都继承同一个父特质的时候,此时可以通过super调用
  9. * 同名方法的时候是按照继承顺序从右向左开始调用
  10. */
  11. trait ParentLog{
  12. def log(msg:String)={
  13. println(s"ParentLog:${msg}")
  14. }
  15. }
  16. trait Log1 extends ParentLog{
  17. override def log(msg: String): Unit = {
  18. println(s"Log1:${msg}")
  19. super.log(msg)
  20. }
  21. }
  22. trait Log2 extends ParentLog{
  23. override def log(msg: String): Unit = {
  24. println(s"Log2:${msg}")
  25. super.log(msg)
  26. }
  27. }
  28. trait Log3 extends ParentLog{
  29. override def log(msg: String): Unit = {
  30. println(s"Log3:${msg}")
  31. super.log(msg)
  32. }
  33. }
  34. class ErrorLog extends Log1 with Log2 with Log3{
  35. override def log(msg: String): Unit = {
  36. println(s"ErrogLog:${msg}")
  37. super.log(msg)
  38. }
  39. }
  40. def main(args: Array[String]): Unit = {
  41. var obj = new ErrorLog
  42. obj.log("hello")
  43. }
  44. }

12.特质自身类型

  1. package com.atguigu.chapter06
  2. import java.io.{FileInputStream, FileOutputStream, ObjectInputStream, ObjectOutputStream}
  3. import scala.beans.BeanProperty
  4. object $12_Self {
  5. /**
  6. * 特质自身类型:提醒子类实现该特质的时候必须提前实现/继承某个特质/class
  7. * 语法:this:类型=>
  8. */
  9. trait ObjectReadAndWrite{
  10. //this:Serializable=>
  11. _:Serializable=>
  12. def read() ={
  13. val ois = new ObjectInputStream(new FileInputStream("d:/obj.txt"))
  14. val ref = ois.readObject()
  15. ois.close()
  16. ref
  17. }
  18. def write()={
  19. val oos = new ObjectOutputStream(new FileOutputStream("d:/obj.txt"))
  20. oos.writeObject(this)
  21. oos.flush()
  22. oos.close()
  23. }
  24. }
  25. class Student extends ObjectReadAndWrite with Serializable {
  26. @BeanProperty
  27. var name:String = _
  28. @BeanProperty
  29. var age:Int = _
  30. }
  31. def main(args: Array[String]): Unit = {
  32. val student = new Student
  33. student.setName("lisi")
  34. student.setAge(20)
  35. student.write()
  36. val s1 = new Student
  37. val ref = s1.read()
  38. val stu = ref.asInstanceOf[Student]
  39. println(stu.getAge)
  40. println(stu.getName)
  41. }
  42. }

13.类型检查和判断

  1. package com.atguigu.chapter06
  2. import scala.util.Random
  3. object $13_TypeCheck {
  4. /**
  5. * java判断对象是否属于某个类型:对象 instanceof 类型
  6. * java中强转: (类型)对象
  7. * java中获取对象的class形式: 对象.getClass
  8. * java中获取类的class形式: 类名.class
  9. *
  10. * scala中判断对象是否属于某个类型: 对象.isInstanceOf[类型]
  11. * scala中强转: 对象.asInstanceOf[类型]
  12. * scala中获取对象的class形式: 对象.getClass<常用>
  13. * scala中获取类的class形式:classOf[类名]<常用>
  14. *
  15. * 新类型:给类起别名
  16. * 语法: type 别名 = 类名
  17. */
  18. val RED = "red" //枚举
  19. class Animal
  20. class Dog extends Animal{
  21. val name = "haha"
  22. }
  23. class Pig extends Animal{
  24. val age = 20
  25. }
  26. def main(args: Array[String]): Unit = {
  27. val animal = getAnimal()
  28. println(animal.getClass)
  29. if(animal.isInstanceOf[Pig]){
  30. val pig = animal.asInstanceOf[Pig]
  31. println(pig.age)
  32. }else{
  33. val dog = animal.asInstanceOf[Dog]
  34. println(dog.name)
  35. }
  36. type MyString = String
  37. val name = new MyString("hello")
  38. println(name)
  39. }
  40. def getAnimal()={
  41. val num = Random.nextInt(10)
  42. if(num%2==0) new Dog
  43. else new Pig
  44. }
  45. }