定义

定义类 class

package tcode.chapter06

object $01_ClassDefind {

class Person
/
java中创建类: [public] class 类名{..}
scala中没有public关键字,默认就是public效果的
scala中创建类: class 类名{..}
scala中创建类的对象: new 类名(..)
/
def main(args: Array[String]): Unit = {

  1. val person = new Person<br /> println(person)<br /> }<br />}

定义方法和字段method、field

package tcode.chapter06

object $02_ClassMethodFields {

class Person{
//属性
//
val name:String = “zhangsan”

  1. var age = 20<br /> //在class中var修饰的属性可以通过_赋予初始值,使用_赋予初始值的时候,属性的类型必须指定<br /> var sex:Boolean = _
  2. //val aa:String = _
  3. private val address = "beijing"
  4. //方法<br /> def add(x:Int,y:Int) = x+y<br /> }<br /> /<br /> java在class中定义属性: [修饰符] 类型 属性名 = 值;<br /> java在class中定义方法: 修饰符 返回值类型 方法名(类型 参数名,...){..}<br /> scala在class中定义属性: [修饰符] val/var 属性名:类型 = 值<br /> 在class中var修饰的属性可以通过_赋予初始值,使用_赋予初始值的时候,属性的类型必须指定<br /> scala在class中定义方法: [修饰符] def 方法名(参数名:类型,..):返回值类型 = {...}<br /> /<br /> def main(args: Array[String]): Unit = {<br /> val person = new Person<br /> println(person.name)<br /> //person.name = "lisi"<br /> println(person.age)<br /> person.age=100<br /> println(person.age)
  5. println(person.sex)
  6. println(person.add(10, 20))<br /> }<br />}

定义构造器constructer

  1. package tcode.chapter06
  2. object $03_ClassContruct {
  3. /
  4. scala中构造器分为两种: 主构造器、辅助构造器
  5. 主构造器
  6. 定义位置: 定义在类名后面用()表示
  7. 语法: class 类名([修饰符] [val/var] 属性名:类型=默认值,.... )
  8. 使用val/var修饰的非private属性与不用val/var修饰的属性的区别:
  9. 使用val/var修饰的非private属性既可以在class内部访问也可以在class外部访问
  10. 不用val/var修饰的属性只能在class内部访问
  11. 辅助构造器
  12. 定义位置: 定义在class内部
  13. 语法: def this(参数名:类型,...){
  14. 辅助构造器第一行必须调用主构造器或者是其他的辅助构造器
  15. this(...)
  16. }
  17. /
  18. class Person(private val name:String ,var age:Int,address:String){// 主构造器
  19. def this(name:String){
  20. this(name,200,"")
  21. }
  22. def this(name:String,age:Int){
  23. this(name)
  24. }
  25. def getAddress() = this.address
  26. }
  27. def main(args: Array[String]): Unit = {
  28. val person = new Person("lisi",20,"shenzhne")
  29. println(person.age)
  30. println(person.getAddress())
  31. val person2 = new Person("wangwu")
  32. println(person2.age)
  33. }
  34. }

特性

封装性private

@BeanProperty

  1. package tcode.chapter06
  2. import com.alibaba.fastjson.JSON
  3. import com.alibaba.fastjson.serializer.SerializeFilter
  4. import scala.beans.BeanProperty
  5. object $04_Private {
  6. class Person{
  7. @BeanProperty
  8. / private /val name:String = "lisi"
  9. @BeanProperty
  10. /private /var age:Int = _
  11. /
  12. def getName() = this.name
  13. def setAge(age:Int) = this.age=age
  14. def getAge() = this.age/
  15. }
  16. /
  17. scala为了兼容javaapi,提供了@BeanProperty,该注解能够自动生成属性的set/get方法
  18. @BeanProperty不能与private一起使用
  19. /
  20. def main(args: Array[String]): Unit = {
  21. val person = new Person
  22. / println(person.getName())
  23. person.setAge(100)
  24. println(person.getAge())/
  25. //json操作
  26. //对象转json
  27. val json = JSON.toJSONString(person, null.asInstanceOf[Array[SerializeFilter]])
  28. println(json)
  29. //json转对象
  30. val js = """{"name":"wangwu","age":200}"""
  31. val p = JSON.parseObject(js,classOf[Person])
  32. println(p.age)
  33. }
  34. }

继承性 extend

  1. package tcode.chapter06
  2. object $05_Extends {
  3. class Person{
  4. private val name = "lsii"
  5. val sex = "man"
  6. var age = 20
  7. def add(x:Int,y:Int) = x+y
  8. }
  9. class Student extends Person{
  10. override val sex = "woman"
  11. //重写方法
  12. override def add(x:Int,y:Int) = {
  13. val k = xy
  14. super.add(k,x)
  15. }
  16. }
  17. /
  18. java中通过extends关键字实现继承
  19. scala中通过extends关键字实现继承
  20. 哪些不能被继承
  21. 1final修饰的class不能被继承
  22. 2、父类private修饰的成员不能被继承
  23. 如果父类定义的成员/方法不适用于子类,子类可以通过override关键字重写val修饰的属性/方法,为什么是val?因为可变的不需要重写,直接改即可
  24. 子类中可以通过super关键字来调用父类的方法
  25. 多态: 父类的引用子类的实例
  26. /
  27. def main(args: Array[String]): Unit = {
  28. val student = new Student
  29. println(student.sex)
  30. println(student.age)
  31. //多态
  32. val p:Person = new Student
  33. println(p.sex)
  34. println(p.age)
  35. }
  36. }

抽象性

😍抽象

  1. package tcode.chapter06
  2. object $07_AbstractClass {
  3. abstract class Dog{
  4. //具体属性
  5. var age:Int =100
  6. var sex:Int
  7. //抽象属性
  8. val name:String
  9. //具体方法
  10. def sum(x:Int,y:Int) = x+y
  11. //抽象方法
  12. def add(x:Int,y:Int):Int
  13. }
  14. class Pig extends Dog{
  15. override var sex: Int = 100
  16. override val name: String = "lisi"
  17. //重写抽象方法
  18. override def add(x: Int, y: Int): Int = x-y
  19. }
  20. /
  21. java中创建抽象类: public abstract class 类名{..}
  22. java的抽象类中可以定义抽象方法
  23. scala抽象类的语法: abstract class 类名{..}
  24. scala抽象类中既可以定义抽象方法,也可以定义具体方法
  25. scala抽象类中既可以定义抽象属性也可以定义具体属性
  26. 抽象方法: 没有方法体的方法称之为抽象方法,定义抽象方法的时候如果方法返回值类型没有定义默认是Unit
  27. 抽象属性: 没有初始化的属性称之为抽象属性
  28. /
  29. def main(args: Array[String]): Unit = {
  30. val pig = new Pig
  31. println(pig.add(10,20))
  32. println(pig.name)
  33. println(pig.sum(20, 30))
  34. println(pig.age)
  35. println(pig.sex)
  36. //匿名子类
  37. val dog = new Dog {
  38. override var sex: Int = 20
  39. override val name: String = "zhangsan"
  40. override def add(x: Int, y: Int): Int = xy
  41. }
  42. println(dog.name)
  43. }
  44. }

🤩特质

特质实现extends .. with .. with..

  1. package tcode.chapter06
  2. object $10_TratiDefined {
  3. trait Logger{
  4. //具体属性
  5. val name = "lisi"
  6. //抽象属性
  7. val age:Int
  8. //抽象方法
  9. def add(x:Int,y:Int):Int
  10. //具体方法
  11. def hello() = println("Hello..........")
  12. }
  13. trait Logger2
  14. trait Logger3
  15. class A
  16. class ErrorLogger extends A with Logger with Logger2 with Logger3 {
  17. override val age: Int = 100
  18. override def add(x: Int, y: Int): Int = x+y
  19. }
  20. /
  21. 特质: 类似java的接口
  22. scala单继承多实现
  23. 特质的语法: trait 特质名{...}, trait相当于interface
  24. 特质中既可以定义抽象方法也可以定义具体方法
  25. 特质中既可以定义抽象属性也可以定义具体属性
  26. 特质的实现:
  27. 1、子类不需要继承父类,只需要实现接口的时候,此时第一个接口的实现通过extends实现,其他接口通过with关键字实现
  28. 2、子类需要继承父类, 此时通过extends关键字继承父类,特质的实现通过with关键字实现
  29. 总结:必须写extends,父类相比接口优先
  30. /
  31. def main(args: Array[String]): Unit = {
  32. val logger = new ErrorLogger
  33. println(logger.name)
  34. println(logger.age)
  35. }
  36. }

特质混入with

package tcode.chapter06

object $11_TraitObject {

trait Logger{
val name = “lisi”
val age = 20
def add(x:Int,y:Int) = x+y
}

class ErrorLogger

/
特质的混入: 让某个对象拥有指定trait的所有属性/方法
语法: new 类名(…) with 特质名

/
def main(args: Array[String]): Unit = {
val logger = new ErrorLogger with Logger //new 类名(…) with 特质名

  1. println(logger.name)
  2. val logger2 = new ErrorLogger<br /> // println(logger2.name)<br /> }<br />}

特质叠加extends .. with .. with..

package tcode.chapter06

object $12_TraitAdd {

trait ParentLogger{
def add(x:Int,y:Int):Int = {
println(“ParentLogger: add”)
x/y
}
}

trait Logger1 extends ParentLogger{

  1. override def add(x:Int,y:Int):Int = {<br /> println("Logger1: add")<br /> super.add(x+y,y)<br /> x<br /> }<br /> }

trait Logger2 extends ParentLogger{
override def add(x:Int,y:Int):Int = {
println(“Logger2: add”)

  1. val k = x-y<br /> //super.add(k,x)<br /> k<br /> }<br /> }

trait Logger3 extends ParentLogger{
override def add(x:Int,y:Int):Int ={
println(“Logger3: add”)
val k = xy
super.add(x,y)
}
}

class ErrorLogger extends Logger1 with Logger2 with Logger3{

  1. override def add(x: Int, y: Int): Int = {<br /> println("ErrorLogger: add")<br /> val k = x+y<br /> //super[Logger2].add(k,xx)<br /> super.add(k,xx)<br /> }<br /> }

/
scala中特质可以多实现,所以如果实现的多个特质中都有同名方法【参数列表也一样】,此时子类调用默认会报错
解决方案: 在子类中重写同名方法
子类通过super关键字调用父trait的同名方法的时候,默认是调用继承顺序最右边的trait的同名方法
子类如果想要调用指定父trait的方法可以通过 super[特质名].方法名 的方式调用
子类如果有继承多个父trait,这多个父triat有同一个父trait的时候,调用同名方法的时候是按照继承顺序从右向左调用
/
def main(args: Array[String]): Unit = {

  1. val logger = new ErrorLogger<br /> println(logger.add(10, 20))<br /> }<br />}自身类型<br />package tcode.chapter06

import java.io.{FileInputStream, FileOutputStream, ObjectInputStream, ObjectOutputStream}

import scala.beans.BeanProperty

object $13_Self {

class Student

trait ObjectReadAndWrite {
_:Serializable => // 告知程序员需要实现这个特质
//从磁盘读取对象
def read() = {
val ois = new ObjectInputStream( new FileInputStream(“d:/obj.txt”) )

  1. val obj = ois.readObject()
  2. ois.close()
  3. obj<br /> }<br /> //将对象写入磁盘<br /> def write() = {
  4. val oos = new ObjectOutputStream( new FileOutputStream("d:/obj.txt") )
  5. oos.writeObject(this)
  6. oos.flush()
  7. oos.close()<br /> }

}

/
自身类型: 告知子类在实现trait的时候必须实现/继承某个指定的类型,起提示作用
语法: this:指定类型 =>
/
class Person extends ObjectReadAndWrite with Serializable {// 需要被告知程序员才会用

  1. @BeanProperty<br /> var name:String = _<br /> @BeanProperty<br /> var age:Int = _<br /> }

def main(args: Array[String]): Unit = {

  1. val person = new Person<br /> person.setAge(100)<br /> person.setName("lisi")
  2. person.write()
  3. val p = new Person<br /> val obj = p.read()<br /> val p2 = obj.asInstanceOf[Person]<br /> println(p2.getName)<br /> }<br />}

创建对象

单例对象object

package tcode.chapter06

object $08_Object {

val name = “lsii”
/
单例对象: object object名
获取单例对象: oject名,意思是要使用这个对象,直接用名字.方法即可
scala object中所有的属性与方法都是类似java static修饰的,所以可以通过 object名称.属性/方法 形式调用
scala class中所有的属性与方法都是类似java 非static修饰的,所以必须通过 对象.属性/方法 形式调用
/
def main(args: Array[String]): Unit = {

  1. println($08_Object)// 因为是对象名,所以打印的是地址<br /> println($08_Object)// 这里打印了多个对象,但是打印出来的地址都是相同的,说明自始至终都是一个对象,即“单例”<br /> println($08_Object)<br /> println($08_Object)<br /> println($08_Object)<br /> println($08_Object.name)<br /> }<br />}

半生类和半生对象ClassAndObject

通过伴生对象的apply方法,实现不使用new方法创建对象。

  1. package tcode.chapter06
  2. object $09_ClassAndObject {
  3. /
  4. 伴生类[class]和伴生对象[object]
  5. 1classobject的名称必须一样
  6. 2classobject必须在同一个源文件[.scala]中
  7. 伴生类和伴生对象能够互相访问对方private修饰的成员
  8. apply方法: 是为了简化伴生类对象的创建
  9. apply方法必须定义在伴生对象中
  10. 定义apply方法之后,后续可以通过 object名.apply()/object名("xx") 方式可以得到伴生类的对象
  11. /
  12. def main(args: Array[String]): Unit = {
  13. //println(Book.age)
  14. val book = new Book// 这里需要new对象,不方便
  15. println(book.getAge())
  16. println(Book.getName())
  17. // 这里直接调用方法,不需要再new了
  18. println(Book.apply().getAge()) Book.apply()等价于new Book //object名.apply()
  19. println(Book().getAge()) 记这条,这条是更简洁的写法,注意“()”不能省略,如果有参数也可以写参数 //object名()
  20. println(Book("shenzhen").address)
  21. Array("spark","scala")
  22. }
  23. }
  24. //如果想让构造器编程私有的:class Book private(val address:String)
  25. class Book(val address:String){
  26. def this() {
  27. this("xxx")
  28. }
  29. private val name = "zhangsan"
  30. def getAge() = Book.age
  31. }
  32. object Book{
  33. private val age = 100
  34. def getName() = {
  35. val book = new Book
  36. book.name
  37. }
  38. def apply(address:String): Book = new Book(address)
  39. def apply(): Book = new Book()
  40. }

//声明包
package tcode.chapter06

import java.util

object $06_Package {

/
包的作用:
1、控制作用域
2、便于管理
3、访问修饰符+包控制访问权限
java的包的用法:
1、导包: import 包名 【导包必须放在package声明之下,class声明之前】
1、导入包下所有类: import 包名.
2、导入包下某个类: import 包名.类
2、声明包: 在源文件第一行通过 package 包名
scala中包的用法:
1、声明包: 在源文件第一行通过 package 包名
2、创建包: 通过 package 包名{..} 创建包
3、导包:
scala可以在任何位置导入包
1、导入包下所有类: import 包名.
2、导入包下某个类: import 包名.类
3、导入包下多个指定类: import 包名.{类名1,类名2,..}
4、导入包下某个类并指定别名: import 包名.{类名=>别名}
5、导入包下除开某个类的所有类: import 包名.{类名=>
, _}
4、包对象
语法: package object 包名{..}
作用: 包对象中定义的非private修饰的属性/方法在包中任何位置都可以使用
5、权限管控
语法:
1、修饰属性:private[包名] val/var 属性 = 值
2、修饰方法: private[包名] def 方法名(..):返回值类型 = {..}
private[包名]代表修饰的属性/方法只能在当前包下使用

/
def main(args: Array[String]): Unit = {

  1. import java.util.{HashMap=>JavaHashMap,ArrayList,HashSet}<br /> //import java.util._<br /> val map = new JavaHashMap[String,String]()<br /> map.put("aa","bb")

}
}
//创建包
package xx{

class Student

object AA{
def main(args: Array[String]): Unit = {

  1. println("---")<br /> println($03_ClassContruct.name)<br /> }<br /> }<br />}

5、权限管控
语法:
1、修饰属性:private[包名] val/var 属性 = 值
2、修饰方法: private[包名] def 方法名(..):返回值类型 = {..}
private[包名]代表修饰的属性/方法只能在当前包下调用,其他包不能使用
// 私有,但chapter06这个包可以调用此私有属性
object $03_ClassContruct {
private [chapter06] val name = “ldc”//声明包
package tcode.chapter06

import java.util

object $06_Package {

/
包的作用:
1、控制作用域
2、便于管理
3、访问修饰符+包控制访问权限
java的包的用法:
1、导包: import 包名 【导包必须放在package声明之下,class声明之前】
1、导入包下所有类: import 包名.
2、导入包下某个类: import 包名.类
2、声明包: 在源文件第一行通过 package 包名
scala中包的用法:
1、声明包: 在源文件第一行通过 package 包名
2、创建包: 通过 package 包名{..} 创建包
3、导包:
scala可以在任何位置导入包
1、导入包下所有类: import 包名.
2、导入包下某个类: import 包名.类
3、导入包下多个指定类: import 包名.{类名1,类名2,..}
4、导入包下某个类并指定别名: import 包名.{类名=>别名}
5、导入包下除开某个类的所有类: import 包名.{类名=>
, _}
4、包对象
语法: package object 包名{..}
作用: 包对象中定义的非private修饰的属性/方法在包中任何位置都可以使用
5、权限管控
语法:
1、修饰属性:private[包名] val/var 属性 = 值
2、修饰方法: private[包名] def 方法名(..):返回值类型 = {..}
private[包名]代表修饰的属性/方法只能在当前包下使用

/
def main(args: Array[String]): Unit = {

  1. import java.util.{HashMap=>JavaHashMap,ArrayList,HashSet}<br /> //import java.util._<br /> val map = new JavaHashMap[String,String]()<br /> map.put("aa","bb")

}
}
//创建包
package xx{

class Student

object AA{
def main(args: Array[String]): Unit = {

  1. println("---")<br /> println($03_ClassContruct.name)<br /> }<br /> }<br />}

5、权限管控
语法:
1、修饰属性:private[包名] val/var 属性 = 值
2、修饰方法: private[包名] def 方法名(..):返回值类型 = {..}
private[包名]代表修饰的属性/方法只能在当前包下使用
// 私有,但chapter06这个包可以调用
object $03_ClassContruct {
private [chapter06] val name = “ldc”

扩展

类型检查和转换

  1. java的类型检查和判断<br /> 1、判断对象是否属于某个类型: 对象 instanceof 类名<br /> 2、将对象强转为指定类型: (类型)对象<br /> javaclass获取<br /> 1、获取对象的class形式: 对象.getClass<br /> 2、获取类的class形式: 类名.class<br /> <br /> scala中类型检查和判断<br /> 1、判断对象是否属于某个类型: 对象.isInstanceOf[类型]<br /> 2、将父类对象强转为指定类型: 对象.asInstanceOf[类型]<br /> scalaclass获取<br /> 1、获取对象的class形式: 对象.getClass,通过父类.getclass来知道到底是哪个子类实现了多态<br /> 2、获取类的class形式: classOf[类名]
  1. package tcode.chapter06
  2. import scala.util.Random
  3. object $14_TypeCheck {
  4. val RED = "red"
  5. def main(args: Array[String]): Unit = {
  6. val animal = getAnimal
  7. println(animal.getClass)
  8. if(animal.isInstanceOf[Pig]){
  9. println(animal.asInstanceOf[Pig].name)
  10. }else{
  11. println(animal.asInstanceOf[Dog].age)
  12. }
  13. }
  14. class Animal
  15. class Pig extends Animal {
  16. val name = "lisi"
  17. }
  18. class Pig2 extends Pig
  19. class Dog extends Animal {
  20. val age = 20
  21. }
  22. def getAnimal() = {
  23. val index = Random.nextInt(10)
  24. if(index%3==0){
  25. new Pig2
  26. }else if(index%5==0){
  27. new Dog
  28. }else{
  29. new Pig
  30. }
  31. }
  32. }

枚举类和应用类

1)说明
枚举类:需要继承Enumeration
应用类:需要继承App
2)案例实操

  1. object Test {
  2. def main(args: Array[String]): Unit = {
  3. println(Color.RED)
  4. }
  5. }
  6. // 枚举类
  7. object Color extends Enumeration {
  8. val RED = Value(1, "red")
  9. val YELLOW = Value(2, "yellow")
  10. val BLUE = Value(3, "blue")
  11. }
  12. // 应用类
  13. object Test20 extends App {
  14. println("xxxxxxxxxxx");
  15. }

Type定义新类型

1)说明
使用type关键字可以定义新的数据数据类型名称,本质上就是类型的一个别名
type 别名 = 类型
2)案例实操

  1. object Test {
  2. def main(args: Array[String]): Unit = {
  3. type S=String
  4. var v:S="abc"
  5. def test():S="xyz"
  6. }
  7. }