Scala面向对象
1. 面向对象概述
- Java / Scala OO(Objecet Orientaed)
- 封装:属性、方法封装到类中
- 继承:父类和子类之间的关系
- 多态:父类引用指向子类对象(重要)
2. 类的定义与使用
/**
* Author: 3zZ.
* Date: 2020/1/3 4:55 下午
*/
object SimpleObjectApp {
def main(args: Array[String]): Unit = {
val person = new People()
person.name = "messi"
// person.age = 30
println(person.name + ".." + person.age)
println("invoke eat method:"+person.eat())
person.watchTv("basailuona")
person.sex()
}
}
class People{
// 定义属性
// var可以自动生成 getter 和 setter
// _ 是占位符
var name:String = _
// val只能自动生成 getter
val age:Int = 10
private [this] val gender = "male"
// 定义方法
def eat():String = {
name+ "eat..."
}
def sex(): Unit ={
println("gender is " + gender)
}
def watchTv(teamName:String): Unit ={
println(name + "is watching " + teamName)
}
}
// 返回
messi..10
invoke eat method:messieat...
messiis watching basailuona
gender is male
- 占位符
_
- 定义占位符必须使用
var
- 定义之前必须先确定变量的类型
- 定义占位符必须使用
private [this]
关键字的变量- 只能在类的内部被拿到
3. 构造器
/**
* Author: 3zZ.
* Date: 2020/1/3 6:23 下午
*/
object ConstructorApp {
def main(args: Array[String]): Unit = {
val person = new Person("zhangsan", 30)
println(person.school + ": "+person.name+" : "+ person.age)
val person2 = new Person("3zz", 18,"M")
println(person2.school + ": "+person2.name+" : "+ person2.age+":"+person2.gender)
}
}
// 主构造器
class Person(val name:String, val age:Int){
println("Constructor enter..")
val school = "ustc"
var gender:String = _
// 附属构造器
def this(name:String, age:Int, gender:String){
this(name, age)// 附属构造器的第一行代码必须要调用主构造器或者其他附属构造器
this.gender = gender
}
println("Constructor leave..")
}
// 返回结果
Constructor enter..
Constructor leave..
ustc: zhangsan : 30
Constructor enter..
Constructor leave..
ustc: 3zz : 18:M
- 主构造器
- class关键字后面括号内的内容
- 附属构造器
- 类内部的
this()
方法,需要在第一行调用主构造器或者其他附属构造器
- 类内部的
- 需要注意的是,如果主构造器中的属性没有
val
或者var
,类外部无法调用该属性
4. 继承与重写
- 继承
/**
* Author: 3zZ.
* Date: 2020/1/3 6:23 下午
*/
object ConstructorApp {
def main(args: Array[String]): Unit = {
val student = new Student("3z",18,"CS")
println(student.name+" : " + student.major)
}
}
// 主构造器
class Person(val name:String, val age:Int){
println("Constructor person enter..")
val school = "ustc"
var gender:String = _
// 附属构造器
def this(name:String, age:Int, gender:String){
this(name, age)// 附属构造器的第一行代码必须要调用主构造器或者其他附属构造器
this.gender = gender
}
println("Constructor person leave..")
}
class Student(name:String, age:Int,val major:String) extends Person(name, age){
println("Constructor student enter..")
println("Constructor student leave..")
}
- 继承的时候还是属性需要注意
- 父类已经有的前面可以没有关键字
- 父类没有的需要添加
val
或者var
- 重写:使用
override
关键字
/**
* Author: 3zZ.
* Date: 2020/1/3 6:23 下午
*/
object ConstructorApp {
def main(args: Array[String]): Unit = {
val student = new Student("3z",18,"CS")
println(student.name+" : " + student.major)
println(student.toString)
}
}
// 主构造器
class Person(val name:String, val age:Int){
println("Constructor person enter..")
val school = "ustc"
println("Constructor person leave..")
}
class Student(name:String, age:Int,val major:String) extends Person(name, age){
println("Constructor student enter..")
// 重写父类中的school属性
override val school = "tsing"
// 重写Object类中的toString()方法
override def toString: String = {
"name: " + name +"age :"+age+"school: " + school
}
println("Constructor student leave..")
}
// 返回结果
Constructor person enter..
Constructor person leave..
Constructor student enter..
Constructor student leave..
3z : CS
name: 3zage :18school: tsing
5. 抽象类
- 类的一个或者多个方法没有完整的实现(只有定义,没有实现)
/**
* Author: 3zZ.
* Date: 2020/1/3 10:01 下午
*/
object AbstractApp {
def main(args: Array[String]): Unit = {
val student = new Student2()
println(student.name)
student.speak
}
}
abstract class Person2{
def speak
val name:String
val age:Int
}
// 需要重写抽象类中的方法和属性
class Student2 extends Person2 {
override def speak: Unit = {
println("speak")
}
override val name: String = "3z"
override val age: Int = 18
}
6. 伴生类与Apply
- 伴生类与伴生对象
/**
* 如果有一个class, 还有一个与class同名的object
* 那么就称这个object是class的伴生对象,class是object的伴生类
*/
// 伴生类
class ApplyTest{
}
// 伴生对象
object ApplyTest{
}
-
apply
方法/** * Author: 3zZ. * Date: 2020/1/3 10:33 下午 */ object ApplyApp { def main(args: Array[String]): Unit = { for (i <- 1 to 10) { ApplyTest.incr } println(ApplyTest.count) // 说明object本身是一个单例对象 val b = ApplyTest() // ==> 默认调用 Object.apply 方法 println("---------------------------") val c = new ApplyTest()// 类名() ====> Class.apply() println(c) // com.zth.fun.ApplyTest@68c4039c c()// 对象() ====> Object.apply() // class applytest apply... } } /** * 如果有一个class, 还有一个与class同名的object * 那么就称这个object是class的伴生对象,class是object的伴生类 */ // 伴生类 class ApplyTest { def apply() = { println("class applytest apply...") } } // 伴生对象 object ApplyTest { println("object applytest enter..") var count = 0 def incr = { count += 1 } // 最佳实践:在Object的apply方法中去new Class def apply() = { println("object applytest apply") // 在object中的apply中new class new ApplyTest } println("object applytest leave..") } // 返回结果 object applytest enter.. object applytest leave.. object applytest apply --------------------------- com.zth.fun.ApplyTest@68c4039c class applytest apply...
- 伴生对象
object
本身是一个单例对象,只会被调用一次 类名()
====>Class.apply()
对象()
====>Object.apply()
apply
方法的最佳实践是在伴生对象的apply
方法中new
一个伴生类
- 伴生对象
7. Case Class
- 通常用在模式匹配里面
/**
* Author: 3zZ.
* Date: 2020/1/3 11:23 下午
*/
// 通常用在模式匹配里面
object CaseClassApp {
def main(args: Array[String]): Unit = {
println(Dog("wangcai").name)
}
}
// case class不用new
case class Dog(name:String)
8. Trait
-
相当于
Java
中的interface
-
Scala
中如何实现多个接口的实现?trait xxx extends aTrait with BTrait // 实际例子 class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging with Serializable