面向对象

概述

OO(Object Oriented)

  • 封装:属性、方法封装到类中,可设置访问级别
  • 继承:父类和子类之间的关系 ,重写
  • 多态:父类引用指向子类对象 ,开发框架基石 Person person = new Person(); User user = new User(); Person person =new User();

类的定义和使用

package org.example
object ObjectApp {
  def main(args: Array[String]): Unit = {
    val person = new People()
    person.name = "szm"
    println(person.name + ".." + person.age)

    println("invoke eat method: " + person.eat)
    person.watchFootball("GuoZU")
    person.printInfo()
    //编译不通过 private 修饰
    //println(person.gender)
  }
}

class People{
  //var(变量)类型自动生成getter/setter
  //val(常量)类型自动生成getter
  //_这种写法就是一个占位符,只可以用于var
  // 定义属性
  var name: String = _
  val age: Int = 10
  private [this] var gender = "male"
  // 定义方法
  def printInfo() : Unit = {
    print("gender: " + gender)
  }
  def eat(): String = {
    name + " eat..."
  }
  def watchFootball(teamName: String): Unit = {
    println(name + " is watching match of " + teamName)
  }
}

invoke eat method: szmy ... Messi is watching match of GuoZu gender: male

构造器

Scala构造器的基本语法:

class 类名(形参列表) {  // 主构造器   注意这种定义格式和java不同
   // 类体
   def  this(形参列表) {  // 辅助构造器
   }
   def  this(形参列表) {  //辅助构造器可以有多个...
   }
} 
object People {
  def main(args: Array[String]): Unit = {
    val s = new Student
    s.name = "tom"
    s.age = 19
    s.printInfo()
  }
}
class Student { // 或者 class Student()  这样写也可以
  var name: String = _
  var age: Int = _
  // 辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑,并且调用的代码一定要放在第一行
  def this(name: String) {
    this() // 直接调用主构造器(主构造器是一个空的构造器)
    this.name = name
    print("this(name: String)")
  }
  def this(name: String, age: Int) {
    this() // 直接调用主构造器
    this.name = name
    this.age = age
    println("this(name: String, age: Int)")
  }
  def this(age: Int) {
    this("jack") // 调用其他辅助构造器,但是这里也间接调用了主构造器,因为 def this(name: String)中调用了主构造器
    this.age = age
  }
  println("主构造器中的语句")
  def printInfo(): Unit = {
    println("name:" + name)
    println("age: " + age)
  }
}

继承和重写

  • 继承
// 如果是父类没有的需要var进行添加
class Student(name: String, age: Int, var major: String) extends Person(name, age) {}
  • 重写
// 父类存在的需要添加关键字 override 
	override def acquireUnrollMemory()
	override def toString = "test override"
package org.example
object ConstructorApp {
  def main(args: Array[String]): Unit = {
    var person =new Person("zhangsan",99)
    println(person.age+":"+person.name)
    var person2 =new Person("zhangsan",99,"Man")
    println(person2.age+":"+person2.name+";"+person2.gender)
  }

}
//主构造器
class Person(val name: String, val age: Int){
  println("Person constructor enter...")
  val school = "ustc"
   //占位符肯定要预先指定类型
  var gender: String = _
  //附属构造器
  def this(name: String , age: Int, gender: String){
    //必须要调用主构造器或者其他附属构造器
    this(name, age)
    this.gender = gender
  }
  override def toString = "test override"
  println("Person Constructor leave...")
}

//继承
//name: String, age: Int, var major: String 继承父类的可以不用直接写var 否则需要重新申明
class Student(name: String, age: Int, var major: String) extends Person(name, age) {

//重写
override val school = "pku"
println("Person Student enter...")
println("Person Student leave...")
}


抽象类

抽线类无法直接实例化,需要通过继承来实例化

package org.example
object AbstractApp {
  def main(args: Array[String]): Unit = {
    var stu =new Student1();
    println(stu.age)
    println(stu.name)
    stu.speak;
  }
}
abstract class Person3{
  def speak
  val name: String
  val age: Int
}

class Student1 extends Person3{
  override def speak: Unit = {
    println("speak")
  }
  override val name: String = "szm"
  override val age: Int = 32
}

伴生类和伴生对象

如果有一个class,还有一个与class同名的object ,则称为两者互为 伴生类和伴生对象


class ApplyTest{
	def apply(){
		println(...)
	}
} 
object ApplyTest{
	def apply(){
		println("Object ApplyTest apply...")
		new ApplyTest
	}
} 
	

类名() ==> Object.apply 对象() ==> Class.apply
最佳实践:在Object的apply方法中去new一个Class

package org.example
object ApplyApp {
  def main(args: Array[String]): Unit = {
//    for(i<-1 to 10){
//      ApplyTest.incr
//    }
//    //object 是一个单例对象
//    println(ApplyTest.count)

    var b=ApplyTest()
    //默认走的是object.apply
    //Object ApplyTest apply...

    println("-----------------------")
    var c= new ApplyTest()
    c()
    //Class ApplyTest apply...
  }

}
class ApplyTest {
  def apply() = {
    println("Class ApplyTest apply...")
  }
}
object ApplyTest {
  println("Object start...")
  var count = 0
  def incr={
    count=count+1
  }
  def apply() = {
    println("Object ApplyTest apply...")
    //在object中的apply中new class
    new ApplyTest
  }
  println("Object end...")
}

case和trait

case class :不用new;通常会用到模式匹配里面

case class Dog(name: String)
// 直接可以调用
Dog("wangcai")

Trait: 类似implements ;第一个使用extends,第二个+使用with即可

trait xxx entends ATrait {

}

trait xxx extends Cloneable with Logging with Serializable{

}

源码中Partition类