第一章.面向对象
1.Scala包
package com.atguigu.chapter06
object $01_Package {
/**
* 包的好处:1.便于区分同名类 2.便于管理
* java中对于包的用法:
* 1.导包:导包的位置必须在package声明之后,类名之前
* 2.导入包下某个类: import 包名.类名
* 3.导入包下所有类: import 包名.*
* 4.声明包: 语法 package 包名 声明包必须在源文件第一行
* scala中对于包的用法
* 1.导包:scala可以在任意位置导入包
* a.导入包下某个类: import 包名.类名
* b.导入包下所有类: import 包名._
* c.导入包下多个类: import 包名.{类名1,类名2,....}
* d.导入包下某个类,并起别名: import 包名.{类名=>别名}
* e.导入包下除开某个类的所有类: import 包名.{类名=>_ , _}
* 2.声明包
* a.语法: package 包名
* b.声明包必须在源文件第一行
* 3.创建包
* a.语法: package 包名{....}
* b.此种方式创建的包只能在classes目录才能看到
* 4.包对象
* a.语法: package object 包名{...}
* b.包对象定义的非private的属性和方法可以在包中任何位置使用
* 5.包与访问修饰符结合
* a.语法: private[包名] val 属性名:类型 = 值
* b.private[包名]修饰的成员只能在指定的包下使用,其他包不能使用
*/
private[chapter06] val sex = "man" //包与访问修饰符结合
import java.util.{HashMap => JavaHashMap} //导入包下所有类
class Person
def main(args: Array[String]): Unit = {
val map = new JavaHashMap[String, Int]()
val p = new xx.Person
}
}
package xx{
class Person
}
2.定义Class
package com.atguigu.chapter06
object $02_ClassDefined {
/**
* java创建类:[访问修饰符] class 类名{....}
* java创建对象: new 类名(....)
*
* scala创建类: class 类名{......}
* scala创建对象: new 类名(.......)
*/
class Person{}
def main(args: Array[String]): Unit = {
val person = new Person
println(person)
}
}
3.定义属性和方法
package com.atguigu.chapter06
object $03_ClassFieldAndMethod {
/**
* java中class定义属性:[访问修饰符] 类型 属性名 = 值
* java中class定义方法: [访问修饰符] 返回值类型 方法名(参数类型 参数名,...){...}
* scala中class定义属性: [访问修饰符] val/var 属性名:类型 = 值
* scala中默认是public效果
* scala在class中定义属性的时候var修饰的属性可以通过_赋予初始值
* scala中class定义方法: [访问修饰符] def 方法名(参数名:类型,...):返回值类型 = {....}
*
*/
class Person{
//定义属性
val name:String = "zhangsan"
//scala在class中定义属性的时候var修饰的属性可以通过_赋予初始值
var age:String = _
val func = (x:Int,y:Int) => x + y
private val address = "shenzhen"
private def add(x:Int,y:Int) = x + y
}
def main(args: Array[String]): Unit = {
val person = new Person
println(person.name)
println(person.age)
println(person.func(10, 20))
//println(person.address)
//println(person.add(10, 20))
}
}
4.构造器
package com.atguigu.chapter06
object $04_Contruct {
/**
* java中构造器的定义
* 1.定义位置: 定义在类内部
* 2.语法: 访问修饰符 类名(参数类型 参数名,...){...}
*
* scala中构造器分为两种
* a.主构造器
* 1.定义位置: 定义在类名后面
* 2.语法: class 类名([访问修饰符] [val/var] 属性名:类型 [=默认值],....)
* 主构造器使用val/var修饰的属性与不使用val/var修饰的属性属性的区别
* 使用val/var修饰的非private属性可以在class内部/外部都可以使用
* 不使用val/var修饰的属性只能在class内部使用
*
* b.辅助构造器
* 1.定义位置: 定义在class内部
* 2.语法: def this(参数名:类型){
* //辅助构造器第一行必须调用其他的辅助构造器或者主构造器
* this(...)
* }
*/
class Person(private val name:String = "zhangsan",var age:Int = 20,address:String){
var money:Double = _
var flag:Boolean = _
def this(flag:Boolean){
this(address="beijing")
this.flag = flag
}
def this(money:Double){
this(true)
this.money=money
}
}
def main(args: Array[String]): Unit = {
val person = new Person(address = "beijing")
//println(person.name)
println(person.age)
//println(person.address)
val person1 = new Person(10.0)
println(person1.flag)
println(person1.money)
val person2 = new Person(false)
println(person2.flag)
}
}
5.封装
package com.atguigu.chapter06
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.serializer.SerializeFilter
import scala.beans.BeanProperty
object $05_Private {
class Person{
@BeanProperty
var name:String = _
@BeanProperty
var age:Int = _
/*def setName(name:String) = this.name =name
def setAge(age:Int) = this.age =age
def getName()= this.name
def getAge()= this.age*/
/**
* java很多Api底层都需要set/get方法,scala为了兼容java的Api,提供了一个注解@BeanProperty,该注解能够自动生成set/get方法
* @BeanProperty注解不能用于private修饰的属性上
*
*/
}
def main(args: Array[String]): Unit = {
val person = new Person
/*person.name="lisi"
person.age=20
println(person.name)*/
person.setName("zhaoliu")
person.setAge(18)
println(person.getName())
//对象转json
val json = JSON.toJSONString(person, null.asInstanceOf[Array[SerializeFilter]])
println(json)
}
}
6.继承
package com.atguigu.chapter06
import scala.util.Random
object $06_Extends {
/**
* java通过extends关键字实现继承
* java通过@overwrite注解实现方法的重写
*
* scala通过extends关键字实现继承
* 哪些不能被继承
* final修饰的class不能被继承
* 父类中private修饰的成员不能被继承
* scala子类可以通过override关键字实现方法实现方法与val属性的重写
* var修饰的属性不能被重写
* scala子类中可以通过super关键字调用父类的方法和属性
* scala中的属性和方法都能做到多态,java只能方法多态
*/
class Person{
private val name = "lisi"
var age:Int = _
val address:String = "shenzhen"
def add(x:Int,y:Int) = x+y
}
class Student extends Person{
//override var age:Int =0
override val address:String="beijing"
override def add(x:Int,y:Int):Int={
x*y
}
}
class Student2 extends Person{
override val address:String="tianjin"
override def add(x: Int, y: Int): Int = x-y
}
def main(args: Array[String]): Unit = {
val student = new Student
println(student.age)
println(student.address)
println(student.add(10, 20))
val person = getPerson()
println(person.add(20, 10))
val p:Person = new Student
println(p.address)
}
def getPerson():Person={
val index = Random.nextInt(10)
if(index % 2 ==0) new Student
else new Student2
}
}
7.抽象类
package com.atguigu.chapter06
object $07_Abstract {
abstract class Animal{
//具体属性
val name:String ="lisi"
//抽象属性
val age:Int
//具体方法
def add(x:Int,y:Int):Int=x+y
//抽象方法
def m1(x:Int,y:Int):Int
}
class Dog extends Animal{
override val age:Int = 20
override def m1(x:Int,y:Int):Int = x-y
}
/**
* java中抽象类的定义: abstract class 类名{...}
*
* scala中抽象类的定义: abstract class 类名{....}
* 抽象方法: 没有方法体的方法称之为抽象方法
* 抽象属性: 没有初始化的属性称之为抽象属性
*
* scala抽象类中既可以定义抽象属性也可以定义具体属性,既可以定义抽象方法也可以定义具体方法
*
*/
def main(args: Array[String]): Unit = {
val dog = new Dog
println(dog.age)
println(dog.m1(10, 20))
//匿名子类
val animal = new Animal {
override val age: Int = 100
override def m1(x: Int, y: Int): Int = x+y
}
println(animal.age)
}
}
8.单例对象(伴生对象)
Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有“静态”内容都可以放置在它的伴生对象中声明。
package com.atguigu.chapter06
object $08_Object {
/**
* 单例对象: object object名称{....}
* object中定义的所有属性和方法都是类似java static修饰的,可以通过 object名称.属性名/方法名 调用
* class中定义的所有属性和方法都是类似java 非static修饰的
*
* 伴生类[class]和伴生对象[object]
* 必须满足两个条件
* a.class与object的名称必须一致
* b.class与object必须在同一个.scala源文件中
* 伴生类和伴生对象的特性:可以互相访问对方private修饰的成员
* apply方法[主要是为了简化伴生类对象的创建]
* 定义位置: 必须定义在伴生对象中
* 定义apply方法之后,就可以通过 object名称.apply(...)/object名称(...) 获取伴生类的对象
*/
def main(args: Array[String]): Unit = {
println($08_Object)
Person.xx()
new Person().yy()
println(Person.getAge())
val person = Person.apply("beijing")
person.yy()
val person2 = Person("tianjin")
println(person2.getName())
}
}
class Person(val address:String){
def this(){
this("")
}
private val age =20
def yy()=println("++++++++++++++++++")
def getName()= Person.name
}
object Person{
private val name ="lisi"
def xx()= println(".............")
def getAge()= new Person().age
def apply(address:String):Person = new Person(address)
def apply():Person = new Person()
}
9.特质
- Scala语言中,采用特质trait(特征)来代替接口的概念,也就是说,多个类具有相同的特征(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。
- Scala中的trait中即可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入(mixin)多个特质。
- Scala引入trait特征,第一可以替代Java的接口,第二个也是对单继承机制的一种补充。
package com.atguigu.chapter06
object $09_TraitDefined {
/**
* scala是单继承多实现
* 特质的语法:trait 特质名{....}
* scala中子类实现特质:
* 1.子类不需要继承父Class,此时子类实现第一个trait使用extends关键字,其他trait的实现使用with关键字
* 2.子类需要继承父class,此时子类实现trait使用with关键字
* 特质中既可以定义具体方法也可以定义抽象方法,既可以定义抽象属性也可以定义具体属性
*
*
*/
trait Log1{
//抽象属性
val name:String
//具体属性
val age = 20
//抽象方法
def m1(x:Int,y:Int):Int
//具体方法
def m2(x:Int) = x*x
}
trait Log2
trait Log3
//子类不需要继承父class,此时子类实现第一个trait使用extends关键字,其他trait的实现使用with关键字
class Errorlog extends Log1 with Log2 with Log3{
override val name:String ="lisi"
override def m1(x: Int, y: Int): Int = x + y
}
class ParentLog
//子类需要继承父class,此时子类实现trait使用with关键字
class WarnLog extends ParentLog with Log1 with Log2 with Log3{
override val name: String = "zhangsan"
override def m1(x: Int, y: Int): Int = x - y
}
def main(args: Array[String]): Unit = {
val log = new Errorlog
println(log.name)
println(log.m1(10, 20))
}
}
10.特质混入
package com.atguigu.chapter06
object $10_ObjectMix {
/**
* 对象混入:让某个对象拥有指定特质的属性和方法
* 语法: new 类名(...) with 特质名
*/
trait Log{
val name = "lisi2"
}
class ErrorLog
def main(args: Array[String]): Unit = {
val log = new ErrorLog
//println(log.name)
val log2 = new ErrorLog with Log
println(log2.name)
}
}
11.特质的叠加
package com.atguigu.chapter06
object $11_TriatAdd {
/**
* 子类可以实现多个父特质,如果这多个父特质都有一个同名方法并且参数列表也一样的时候,此时子类默认调用该同名方法会报错
* 子类可以通过重写该同名方法来解决报错问题
* 子类中如果想要调用父类的同名方法可以使用super.方法名的方式调用,此时默认情况下调用的是继承顺序最后一个特质的同名方法
* 如果子类想要调用指定父特质的同名方法可以使用super[特质名].方法名的方式调用
* 子类可以实现多个父特质,如果这多个父特质中都有一个同名方法并且参数列表也一样的时候,并且这多个特质都继承同一个父特质的时候,此时可以通过super调用
* 同名方法的时候是按照继承顺序从右向左开始调用
*/
trait ParentLog{
def log(msg:String)={
println(s"ParentLog:${msg}")
}
}
trait Log1 extends ParentLog{
override def log(msg: String): Unit = {
println(s"Log1:${msg}")
super.log(msg)
}
}
trait Log2 extends ParentLog{
override def log(msg: String): Unit = {
println(s"Log2:${msg}")
super.log(msg)
}
}
trait Log3 extends ParentLog{
override def log(msg: String): Unit = {
println(s"Log3:${msg}")
super.log(msg)
}
}
class ErrorLog extends Log1 with Log2 with Log3{
override def log(msg: String): Unit = {
println(s"ErrogLog:${msg}")
super.log(msg)
}
}
def main(args: Array[String]): Unit = {
var obj = new ErrorLog
obj.log("hello")
}
}
12.特质自身类型
package com.atguigu.chapter06
import java.io.{FileInputStream, FileOutputStream, ObjectInputStream, ObjectOutputStream}
import scala.beans.BeanProperty
object $12_Self {
/**
* 特质自身类型:提醒子类实现该特质的时候必须提前实现/继承某个特质/class
* 语法:this:类型=>
*/
trait ObjectReadAndWrite{
//this:Serializable=>
_:Serializable=>
def read() ={
val ois = new ObjectInputStream(new FileInputStream("d:/obj.txt"))
val ref = ois.readObject()
ois.close()
ref
}
def write()={
val oos = new ObjectOutputStream(new FileOutputStream("d:/obj.txt"))
oos.writeObject(this)
oos.flush()
oos.close()
}
}
class Student extends ObjectReadAndWrite with Serializable {
@BeanProperty
var name:String = _
@BeanProperty
var age:Int = _
}
def main(args: Array[String]): Unit = {
val student = new Student
student.setName("lisi")
student.setAge(20)
student.write()
val s1 = new Student
val ref = s1.read()
val stu = ref.asInstanceOf[Student]
println(stu.getAge)
println(stu.getName)
}
}
13.类型检查和判断
package com.atguigu.chapter06
import scala.util.Random
object $13_TypeCheck {
/**
* java判断对象是否属于某个类型:对象 instanceof 类型
* java中强转: (类型)对象
* java中获取对象的class形式: 对象.getClass
* java中获取类的class形式: 类名.class
*
* scala中判断对象是否属于某个类型: 对象.isInstanceOf[类型]
* scala中强转: 对象.asInstanceOf[类型]
* scala中获取对象的class形式: 对象.getClass<常用>
* scala中获取类的class形式:classOf[类名]<常用>
*
* 新类型:给类起别名
* 语法: type 别名 = 类名
*/
val RED = "red" //枚举
class Animal
class Dog extends Animal{
val name = "haha"
}
class Pig extends Animal{
val age = 20
}
def main(args: Array[String]): Unit = {
val animal = getAnimal()
println(animal.getClass)
if(animal.isInstanceOf[Pig]){
val pig = animal.asInstanceOf[Pig]
println(pig.age)
}else{
val dog = animal.asInstanceOf[Dog]
println(dog.name)
}
type MyString = String
val name = new MyString("hello")
println(name)
}
def getAnimal()={
val num = Random.nextInt(10)
if(num%2==0) new Dog
else new Pig
}
}