定义
定义类 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 = {
val person = new Person<br /> println(person)<br /> }<br />}
定义方法和字段method、field
package tcode.chapter06
object $02_ClassMethodFields {
class Person{
//属性
//
val name:String = “zhangsan”
var age = 20<br /> //在class中var修饰的属性可以通过_赋予初始值,使用_赋予初始值的时候,属性的类型必须指定<br /> var sex:Boolean = _
//val aa:String = _
private val address = "beijing"
//方法<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)
println(person.sex)
println(person.add(10, 20))<br /> }<br />}
定义构造器constructer
package tcode.chapter06
object $03_ClassContruct {
/
scala中构造器分为两种: 主构造器、辅助构造器
主构造器
定义位置: 定义在类名后面用()表示
语法: class 类名([修饰符] [val/var] 属性名:类型=默认值,.... )
使用val/var修饰的非private属性与不用val/var修饰的属性的区别:
使用val/var修饰的非private属性既可以在class内部访问也可以在class外部访问
不用val/var修饰的属性只能在class内部访问
辅助构造器
定义位置: 定义在class内部
语法: def this(参数名:类型,...){
辅助构造器第一行必须调用主构造器或者是其他的辅助构造器
this(...)
}
/
class Person(private val name:String ,var age:Int,address:String){// 主构造器
def this(name:String){
this(name,200,"")
}
def this(name:String,age:Int){
this(name)
}
def getAddress() = this.address
}
def main(args: Array[String]): Unit = {
val person = new Person("lisi",20,"shenzhne")
println(person.age)
println(person.getAddress())
val person2 = new Person("wangwu")
println(person2.age)
}
}
特性
封装性private
@BeanProperty
package tcode.chapter06
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.serializer.SerializeFilter
import scala.beans.BeanProperty
object $04_Private {
class Person{
@BeanProperty
/ private /val name:String = "lisi"
@BeanProperty
/private /var age:Int = _
/
def getName() = this.name
def setAge(age:Int) = this.age=age
def getAge() = this.age/
}
/
scala为了兼容java的api,提供了@BeanProperty,该注解能够自动生成属性的set/get方法
@BeanProperty不能与private一起使用
/
def main(args: Array[String]): Unit = {
val person = new Person
/ println(person.getName())
person.setAge(100)
println(person.getAge())/
//json操作
//对象转json
val json = JSON.toJSONString(person, null.asInstanceOf[Array[SerializeFilter]])
println(json)
//json转对象
val js = """{"name":"wangwu","age":200}"""
val p = JSON.parseObject(js,classOf[Person])
println(p.age)
}
}
继承性 extend
package tcode.chapter06
object $05_Extends {
class Person{
private val name = "lsii"
val sex = "man"
var age = 20
def add(x:Int,y:Int) = x+y
}
class Student extends Person{
override val sex = "woman"
//重写方法
override def add(x:Int,y:Int) = {
val k = xy
super.add(k,x)
}
}
/
java中通过extends关键字实现继承
scala中通过extends关键字实现继承
哪些不能被继承
1、final修饰的class不能被继承
2、父类private修饰的成员不能被继承
如果父类定义的成员/方法不适用于子类,子类可以通过override关键字重写val修饰的属性/方法,为什么是val?因为可变的不需要重写,直接改即可
子类中可以通过super关键字来调用父类的方法
多态: 父类的引用子类的实例
/
def main(args: Array[String]): Unit = {
val student = new Student
println(student.sex)
println(student.age)
//多态
val p:Person = new Student
println(p.sex)
println(p.age)
}
}
抽象性
😍抽象
package tcode.chapter06
object $07_AbstractClass {
abstract class Dog{
//具体属性
var age:Int =100
var sex:Int
//抽象属性
val name:String
//具体方法
def sum(x:Int,y:Int) = x+y
//抽象方法
def add(x:Int,y:Int):Int
}
class Pig extends Dog{
override var sex: Int = 100
override val name: String = "lisi"
//重写抽象方法
override def add(x: Int, y: Int): Int = x-y
}
/
java中创建抽象类: public abstract class 类名{..}
java的抽象类中可以定义抽象方法
scala抽象类的语法: abstract class 类名{..}
scala抽象类中既可以定义抽象方法,也可以定义具体方法
scala抽象类中既可以定义抽象属性也可以定义具体属性
抽象方法: 没有方法体的方法称之为抽象方法,定义抽象方法的时候如果方法返回值类型没有定义默认是Unit
抽象属性: 没有初始化的属性称之为抽象属性
/
def main(args: Array[String]): Unit = {
val pig = new Pig
println(pig.add(10,20))
println(pig.name)
println(pig.sum(20, 30))
println(pig.age)
println(pig.sex)
//匿名子类
val dog = new Dog {
override var sex: Int = 20
override val name: String = "zhangsan"
override def add(x: Int, y: Int): Int = xy
}
println(dog.name)
}
}
🤩特质
特质实现extends .. with .. with..
package tcode.chapter06
object $10_TratiDefined {
trait Logger{
//具体属性
val name = "lisi"
//抽象属性
val age:Int
//抽象方法
def add(x:Int,y:Int):Int
//具体方法
def hello() = println("Hello..........")
}
trait Logger2
trait Logger3
class A
class ErrorLogger extends A with Logger with Logger2 with Logger3 {
override val age: Int = 100
override def add(x: Int, y: Int): Int = x+y
}
/
特质: 类似java的接口
scala单继承多实现
特质的语法: trait 特质名{...}, trait相当于interface
特质中既可以定义抽象方法也可以定义具体方法
特质中既可以定义抽象属性也可以定义具体属性
特质的实现:
1、子类不需要继承父类,只需要实现接口的时候,此时第一个接口的实现通过extends实现,其他接口通过with关键字实现
2、子类需要继承父类, 此时通过extends关键字继承父类,特质的实现通过with关键字实现
总结:必须写extends,父类相比接口优先
/
def main(args: Array[String]): Unit = {
val logger = new ErrorLogger
println(logger.name)
println(logger.age)
}
}
特质混入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 特质名
println(logger.name)
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{
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”)
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{
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 = {
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”) )
val obj = ois.readObject()
ois.close()
obj<br /> }<br /> //将对象写入磁盘<br /> def write() = {
val oos = new ObjectOutputStream( new FileOutputStream("d:/obj.txt") )
oos.writeObject(this)
oos.flush()
oos.close()<br /> }
}
/
自身类型: 告知子类在实现trait的时候必须实现/继承某个指定的类型,起提示作用
语法: this:指定类型 =>
/
class Person extends ObjectReadAndWrite with Serializable {// 需要被告知程序员才会用
@BeanProperty<br /> var name:String = _<br /> @BeanProperty<br /> var age:Int = _<br /> }
def main(args: Array[String]): Unit = {
val person = new Person<br /> person.setAge(100)<br /> person.setName("lisi")
person.write()
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 = {
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方法创建对象。
package tcode.chapter06
object $09_ClassAndObject {
/
伴生类[class]和伴生对象[object]
1、class与object的名称必须一样
2、class与object必须在同一个源文件[.scala]中
伴生类和伴生对象能够互相访问对方private修饰的成员
apply方法: 是为了简化伴生类对象的创建
apply方法必须定义在伴生对象中
定义apply方法之后,后续可以通过 object名.apply()/object名("xx") 方式可以得到伴生类的对象
/
def main(args: Array[String]): Unit = {
//println(Book.age)
val book = new Book// 这里需要new对象,不方便
println(book.getAge())
println(Book.getName())
// 这里直接调用方法,不需要再new了
println(Book.apply().getAge()) Book.apply()等价于new Book //object名.apply()
println(Book().getAge()) 记这条,这条是更简洁的写法,注意“()”不能省略,如果有参数也可以写参数 //object名()
println(Book("shenzhen").address)
Array("spark","scala")
}
}
//如果想让构造器编程私有的:class Book private(val address:String)
class Book(val address:String){
def this() {
this("xxx")
}
private val name = "zhangsan"
def getAge() = Book.age
}
object Book{
private val age = 100
def getName() = {
val book = new Book
book.name
}
def apply(address:String): Book = new Book(address)
def apply(): Book = new Book()
}
包
//声明包
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 = {
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 = {
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 = {
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 = {
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”
扩展
类型检查和转换
java的类型检查和判断<br /> 1、判断对象是否属于某个类型: 对象 instanceof 类名<br /> 2、将对象强转为指定类型: (类型)对象<br /> java中class获取<br /> 1、获取对象的class形式: 对象.getClass<br /> 2、获取类的class形式: 类名.class<br /> <br /> scala中类型检查和判断<br /> 1、判断对象是否属于某个类型: 对象.isInstanceOf[类型]<br /> 2、将父类对象强转为指定类型: 对象.asInstanceOf[类型]<br /> scala中class获取<br /> 1、获取对象的class形式: 对象.getClass,通过父类.getclass来知道到底是哪个子类实现了多态<br /> 2、获取类的class形式: classOf[类名]
package tcode.chapter06
import scala.util.Random
object $14_TypeCheck {
val RED = "red"
def main(args: Array[String]): Unit = {
val animal = getAnimal
println(animal.getClass)
if(animal.isInstanceOf[Pig]){
println(animal.asInstanceOf[Pig].name)
}else{
println(animal.asInstanceOf[Dog].age)
}
}
class Animal
class Pig extends Animal {
val name = "lisi"
}
class Pig2 extends Pig
class Dog extends Animal {
val age = 20
}
def getAnimal() = {
val index = Random.nextInt(10)
if(index%3==0){
new Pig2
}else if(index%5==0){
new Dog
}else{
new Pig
}
}
}
枚举类和应用类
1)说明
枚举类:需要继承Enumeration
应用类:需要继承App
2)案例实操
object Test {
def main(args: Array[String]): Unit = {
println(Color.RED)
}
}
// 枚举类
object Color extends Enumeration {
val RED = Value(1, "red")
val YELLOW = Value(2, "yellow")
val BLUE = Value(3, "blue")
}
// 应用类
object Test20 extends App {
println("xxxxxxxxxxx");
}
Type定义新类型
1)说明
使用type关键字可以定义新的数据数据类型名称,本质上就是类型的一个别名
type 别名 = 类型
2)案例实操
object Test {
def main(args: Array[String]): Unit = {
type S=String
var v:S="abc"
def test():S="xyz"
}
}