第6章 面向对象
6.1. Scala包
-
包的命名
-
包的导入
-
Scala中基本的import导入语法和Java完全一致
import java.util.List import java.util._ // Scala中使用下划线代替Java中的星号
-
Java中import导入的语法比较单一,Scala对此进行扩展,Scala中的import语法可以在任意位置使用
object ScalaImport{def main(args: Array[String]): Unit = {import java.util.ArrayListnew ArrayList()} }
-
Scala中可以导包,而不是导类
object ScalaImport{def main(args: Array[String]): Unit = {import java.utilnew util.ArrayList()}}
-
Scala中可以在同一行中导入多个类,简化代码
import java.util.{List, ArrayList}
-
Scala中可以屏蔽某个包中的类
import java.util._ import java.sql.{ Date=>_, Array=>_, _ }
-
Scala中可以给类起别名,简化使用
import java.util.{ArrayList=>AList}object ScalaImport{def main(args: Array[String]): Unit = {new AList()} }
-
Scala中可以使用类的绝对路径而不是相对路径
import _root_.java.util.ArrayList
-
默认情况下,Scala中会导入如下包和对象
import java.lang._ import scala._ Import scala.Predef._
-
6.2 类和对象
-
类和对象
package chapter06import scala.beans.BeanPropertyobject Test03_Class {def main(args: Array[String]): Unit = {val student = new Student()// println(student.name) // 不能访问private属性println(student.age)println(student.sex)student.sex = "male"println(student.sex)}}// 定义一个类 class Student{// 定义属性// 生成get和set方法private var name: String = "Alice"// 初值为空, 0,必须定义var@BeanPropertyvar age: Int = _// 初值为空, null,必须定义var@BeanPropertyvar sex: String = _}
-
封装
-
访问权限
package chapter06import scala.beans.BeanPropertyobject Test04_Access {def main(args: Array[String]): Unit = {// 创建对象val person = new Person() // person.idCard // error // person.name // errorprintln(person.sex)println(person.age)person.printInfo()val worker = new Worker()// worker.idCard // error// worker.name // errorprintln(worker.sex)println(worker.age)worker.printInfo()}}// 定义一个子类 class Worker extends Person {override def printInfo(): Unit = {println(s"Worker:") // println($idCard) // errorname = "bob"age = 25sex = "male"println(s"Worker: $name ${sex} $age")} }
package chapter06object Test04_ClassForAccess {}// 定义一个父类 class Person {// 只能在当前类访问和伴生对象访问private var idCard: String = "123456"// 只能在当前类和子类访问protected var name: String = "Alice"var sex: String = "female"private[chapter06] var age: Int = 18def printInfo() = {println(s"Person: $idCard $name ${sex} $age")} }
-
构造器
和类名一样的方法
package chapter06object Test05_Constructor {def main(args: Array[String]): Unit = {val student1 = new Student1()student1.Student1()val student2 = new Student1("scc")student2.Student1()val student3 = new Student1("zyy", 18)student3.Student1()}}// 定义一个类 class Student1() {var name: String = _var age: Int = _println(s"1. 主构造方法被调用 $name $age")// 声明辅助构造方法def this(name: String) = {this() // 直接调用主构造器println(s"2. 辅助构造方法一被调用 $name $age")this.name = nameprintln(s"name: $name age: $age")}def this(name: String, age: Int) = {this(name) // 直接调用辅助构造器一println(s"3. 辅助构造方法二被调用 $name $age")this.name = namethis.age = ageprintln(s"name: $name age: $age")}// 此处不是构造方法def Student1() = {println(s"一般方法被调用")}}
1. 主构造方法被调用 null 0 一般方法被调用 1. 主构造方法被调用 null 0 2. 辅助构造方法一被调用 scc 0 name: scc age: 0 一般方法被调用 1. 主构造方法被调用 null 0 2. 辅助构造方法一被调用 zyy 0 name: zyy age: 0 3. 辅助构造方法二被调用 zyy 18 name: zyy age: 18 一般方法被调用
-
构造器参数
package chapter06object Test06_ConstructorParams {def main(args: Array[String]): Unit = {val student2 = new Student2student2.name = "Alice"student2.age = 18println(s"student2 name: ${student2.name}, age: ${student2.age}")val student3 = new Student3("scc", 18)println(s"student3 name: ${student3.name}, age: ${student3.age}")val student4 = new Student4("bob", 29)println(s"student4 name: ${student4.name}, age: ${student4.age}")val student6 = new Student6("bob", 29,"南京理工")student6.printInfoprintln(s"student6 name: ${student6.name}, age: ${student6.age}")}}// 定义一个类 // 无参构造器 class Student2() {// 单独定义属性var name: String = _var age: Int = _ }// 主构造器参数有var修饰,上面定义等价于,name和age为属性,不需要new和单独赋值,推荐这种写法 class Student3(var name: String, var age: Int)// 主构造器参数无修饰,此时_name和_age为形参 // 非常不推荐 class Student4(_name: String, _age: Int) {var name = _namevar age = _age }// val 属性值不能修改 class Student5(val name: String, val age: Int)// 主构造器有参数 class Student6(var name: String, var age: Int) {var school: String = _def this(name: String, age: Int, school: String) = {// 先调用主构造器有参数this(name, age)// 先调用辅助构造器有参数this.school = school}def printInfo = {println(s"student6 name: ${this.name}, age: ${this.age}, school: ${this.school}")}}
-
继承
package chapter06object Test07_Inherit {def main(args: Array[String]): Unit = {/*** 1. 父类的主构造器调用* 2. 父类的辅助构造器调用* 3. 子类的主构造器被调用*/val student1 = new Student7("scc", 18)/*** 1. 父类的主构造器调用* 2. 父类的辅助构造器调用* 3. 子类的主构造器被调用* 4. 子类的辅助构造器被调用*/val student2 = new Student7("scc", 18, "0001")}}// 定义一个父类 class Person7() {var name: String = _var age: Int = _println("1. 父类的主构造器调用")def this(name: String, age: Int) = {this()println("2. 父类的辅助构造器调用")this.name = namethis.age = age}def printInfo = {println(s"Person7: $name $age")}}// 定义一个子类 // name和age为构造器参数,不是属性 // extends Person7(name, age) 和 extends Person7不一样,后者不会调用辅助构造器 class Student7(name: String, age: Int) extends Person7(name, age) {var studentNum: String = _println("3. 子类的主构造器被调用")def this(name: String, age: Int, studentNum: String) = {// 调用主构造器,先调用父类构造器,再调用子类构造器this(name, age)println("4. 子类的辅助构造器被调用")this.studentNum = studentNum}override def printInfo: Unit = {println(s"Student7: $name $age $studentNum")}}
-
多态
定义:一种接口,可以有多种实现方式
通过运行时,动态绑定手段,实现多态
scala属性和方法都是动态绑定的
-
抽象类
package chapter06object Test09_Abstract {def main(args: Array[String]): Unit = {val student = new Student9student.eat()student.sleep()} }// 定义抽象类 abstract class Person9() {//非抽象属性val name: String = "person"// 抽象属性var age: Int// 非抽象方法def eat(): Unit = {println("person eat")}// 抽象方法def sleep(): Unit}// 定义具体的实现子类 class Student9 extends Person9 {// 实现抽象属性和方法override var age: Int = 18override def sleep(): Unit = {println("student sleep")}//实现非抽象属性和方法,此时name在父类中是val类型override val name: String = "student"override def eat(): Unit = {super.eat()println("student eat")} }
-
匿名子类
package chapter06// 匿名子类 object Test10_AnnoymousSubClass {def main(args: Array[String]): Unit = {val person: Person10 = new Person10 {override var name: String = "scc"override def eat(): Unit = {println(s"${name} eat!")}}println(person.name)person.eat()}}// 定义抽象类 abstract class Person10 {var name: Stringdef eat(): Unit}
-
单例对象/伴生对象
package chapter06object Test11_Object {def main(args: Array[String]): Unit = {// 1. private 构造方法私有化时,下面语句会报错// val student = new Student11("alice", 18)// student.printInfo()val student1: Student11 = Student11.newStudents("alice", 19)student1.printInfo()val student2: Student11 = Student11.apply("scc", 19)student2.printInfo()// 调用时,可以直接省略applyval student3: Student11 = Student11("zyy", 19)student3.printInfo()}}// 定义类,private 构造方法私有化 class Student11 private(val name: String, val age: Int) {def printInfo(): Unit = {println(s"student name: ${name}, age: ${age}, school: ${Student11.school}")} }// 定义伴生对象 object Student11 {val school: String = "atguigu"// 定义一个类的对象实例的创建方法或者工厂方法def newStudents(name: String, age: Int): Student11 = {new Student11(name, age)}// 定义一个特殊的方法,此方法有个特殊用法,调用时,可以直接省略applydef apply(name: String, age: Int): Student11 = {new Student11(name, age)} }
-
单例设计模式
饿汉式和懒汉式
package chapter06object Test12_Singleton {def main(args: Array[String]): Unit = {val student1 = Student12.getInstance()student1.printInfo()// 真的只有一份吗?不信,再执行一遍val student2 = Student12.getInstance()student2.printInfo()println(student1)println(student2)println(student1.eq(student2))}}// 定义类,private 构造方法私有化 class Student12 private(val name: String, val age: Int) {def printInfo(): Unit = {println(s"student name: ${name}, age: ${age}, school: ${Student11.school}")} }// 定义伴生对象 // 单例设计模式,饿汉式,低效 //object Student12 { // private val student: Student12 = new Student12("alice", 18) // // def getInstance():Student12={ // student // } //}// 定义伴生对象 // 单例设计模式,懒汉式,高效,不存在时,创建,对象存在时,不创建, object Student12 {private var student: Student12 = _def getInstance(): Student12 = {if (student == null) {// 如果没有对象实例,则创建一个student = new Student12("alice", 18)}student}}
-
特质(trait)
-
特质
package chapter06object Test13_Trait {def main(args: Array[String]): Unit = {val student = new Student13()student.sayHello()student.dating()student.study()student.play()/*** hello from student* hello from student student* student student is dating* student student is study* young people student is playing*/}}// 定义一个父类 class Person13 {val name: String = "person"var age: Int = 18def sayHello(): Unit = {println("hello from " + name)} }// 定义一个特质 trait Young {// 声明抽象和非抽象属性var age: Intval name: String = "young"// 声明抽象和非抽象方法def play(): Unit = {println(s"young people ${name} is playing")}def dating(): Unit }class Student13 extends Person13 with Young {// 重写冲突的属性override val name = "student"// 实现抽象方法override def dating(): Unit = {println(s"student ${name} is dating")}// 定义具体方法def study(): Unit = println(s"student ${name} is study")override def sayHello(): Unit = {// 就近原则super.sayHello()println(s"hello from student ${name}")}}
-
特质的混入
package chapter06object Test14_TraitMixin {def main(args: Array[String]): Unit = {val student = new Student14/*** student student is study* student student konwledge is increase 1*/student.study()student.increase()/*** young people student is playing* student student konwledge is increase 2*/student.play()student.increase()/*** student student is dating* student student konwledge is increase 3*/student.dating()student.increase()} }// 再定义一个特质 trait Knowledge {var amount: Int = 0def increase(): Unit }class Student14 extends Person13 with Young with Knowledge {// 重写冲突的属性override val name = "student"// 实现抽象方法override def dating(): Unit = {println(s"student ${name} is dating")}// 定义具体方法def study(): Unit = println(s"student ${name} is study")override def sayHello(): Unit = {// 就近原则super.sayHello()println(s"hello from student ${name}")}// 实现特质中的抽象方法override def increase(): Unit = {amount += 1println(s"student ${name} konwledge is increase ${amount}")}}
-
特质的叠加+钻石问题,从右到左叠加
package chapter06object Test15_TraitOverlying {def main(args: Array[String]): Unit = {val student = new Student15/*** konwledge increased*/student.increase()//钻石问题特征叠加/*** my ball is a red-foot-ball*/val myFootBall = new MyFootBallprintln(myFootBall.describe())}}// 再定义一个特质 trait Knowledge15 {var amount: Int = 0def increase(): Unit = {println(s"konwledge increased")} }// 再定义一个特质 trait Talent15 {def singing(): Unitdef dancing(): Unitdef increase(): Unit = {println(s"talent increased")} }// 首先调用最后一个特质的方法 class Student15 extends Person13 with Talent15 with Knowledge15 {override def singing(): Unit = {println("student is singing")}override def dancing(): Unit = {println("student is dancing")}override def increase(): Unit = super.increase() }// 定义一个球类 trait Ball {def describe(): String = {"ball"} }// 定义颜色特征 trait ColorBall extends Ball {val color: String = "red"override def describe(): String = {color + "-" + super.describe()} }// 定义种类特征 trait CategoryBall extends Ball {val category: String = "foot"override def describe(): String = {category + "-" + super.describe()} }// 定义一个自定义球类 class MyFootBall extends CategoryBall with ColorBall {override def describe(): String = "my ball is a " + super.describe()}
-
钻石问题的特质叠加
-
特质和抽象类的区别
-
类型转换和转换
package chapter06object Test17_Extends {def main(args: Array[String]): Unit = {//1. 类型的转化和检测val student = new Student17("alice", 18)/*** hi from student alice* student alice is study*/student.sayHi()student.study()/*** hi from student alice*/val person: Person17 = new Student17("alice", 18)person.sayHi()/*** 类型判断* student is Student17: true* student is Person17: true* person is Person17: true* person is Student17: true*/println("student is Student17: " + student.isInstanceOf[Student17])println("student is Person17: " + student.isInstanceOf[Person17])println("person is Person17: " + person.isInstanceOf[Person17])// 体现多态println("person is Student17: " + person.isInstanceOf[Student17])val person2: Person17 = new Person17("alice", 18)/*** person is Person17: true* person is Student17: false*/println("person is Person17: " + person2.isInstanceOf[Person17])println("person is Student17: " + person2.isInstanceOf[Student17])// 类型转换if (person.isInstanceOf[Student17]) {val newStudent: Student17 = person.asInstanceOf[Student17]newStudent.study()}println(classOf[Student17])}}class Person17(val name: String, val age: Int) {def sayHi(): Unit = {println(s"hi from person $name")} }class Student17(name: String, age: Int) extends Person17(name = name, age = age) {override def sayHi(): Unit = {println(s"hi from student $name")}def study(): Unit = {println(s"student $name is study")} }