56 Scala面向对象

类和对象

创建类和对象

  • main方法必须放在Object中
  • 如果类是空的,没有任何成员,可以省略{}
  • 如果构造器的参数为空,可以省略()
object demo01 {
  //创建类。省略花括号
  class Person

  def main(args: Array[String]): Unit = {
    //创建对象。省略括号
    val person = new Person
    println(person)
  }
}

定义和访问成员变量

object demo01 {
  class Person {
    //定义成员变量
    var name = ""
    var age = 0
  }

  def main(args: Array[String]): Unit = {
    //创建Person对象
    val person = new Person
    person.name = "zhangsan"
    person.age = 20

    //获取变量的值
    println(person.name)
    println(person.age)
  }
}

使用下划线初始化成员变量

  • 在定义var类型的成员变量时,可以使用_来初始化成员变量
  • val类型的变量,必须要自己手动初始化
object demo01 {
  class Person {
    //使用下划线进行初始化
    var name:String = _
    var age:Int = _
  }

  def main(args: Array[String]): Unit = {
    val person = new Person

    println(person.name)
    println(person.age)
  }
}

定义成员方法

object demo01 {
  class Customer {
    var name:String = _
    var sex:String = _

    //定义成员方法
    def sayHi(msg:String) = {
      println(msg)
    }
  }

  def main(args: Array[String]): Unit = {
    val customer = new Customer
    customer.name = "zhangsan"
    customer.sex = "male"
    customer.sayHi("hello")
  }
}

成员访问修饰符

  • 可以在成员前面添加private/protected关键字
  • scala中没有public
  • 任何没有被标为private或protected的成员都是公共的
object demo01 {
  class Person {
    //定义私有成员变量
    private var name:String = _
    private var age:Int = _

    def getName() = name
    def setName(name:String) = this.name = name
    def getAge() = age
    def setAge(age:Int) = this.age = age
    
    //定义私有成员方法
    private def getNameAndAge = name -> age
  }

  def main(args: Array[String]): Unit = {
    val person = new Person
    person.setName("zhangsan")
    person.setAge(10)

    println(person.getName())
    println(person.getAge())
  }
}

构造器

主构造器

  • 主构造器的参数列表直接定义在类名后面
  • 添加了var/val表示直接通过主构造器定义成员变量
  • 构造器参数列表可以指定默认值
  • 创建实例,调用构造器可以指定字段进行初始化
  • 整个class中除了字段定义和方法定义的代码,都是构造代码
object demo01 {
  //定义类的主构造器,并指定默认值
  class Person(var name:String = "", var age:Int = 0){
    println("调用主构造器")
  }

  def main(args: Array[String]): Unit = {
    //不传入任何参数
    val empty = new Person
    
    //给构造器传入参数
    val zhangsan = new Person("zhangsan", 20)
    
    //指定字段进行初始化
    val man = new Person(age = 40)
  }
}

辅助构造器

  • 辅助构造器的第一行代码,必须要调用主构造器或者其他辅助构造器
object demo01 {
  class Customer(var name:String = "", var address:String = ""){
    //定义辅助构造器
    def this(array: Array[String]) = {
      this(array(0), array(1))
    }
  }

  def main(args: Array[String]): Unit = {
    val zhangsan = new Customer(Array("zhangsan", "beijing"))

    println(zhangsan.name)
    println(zhangsan.address)
  }
}

单例对象

  • scala中没有中java的静态成员,要想定义类似于Java的static变量、static方法
  • 就要使用到scala中的单例对象——object

单例对象

object demo01 {
  //定义一个单例对象
  object Dog {
    val LEG_NUM = 4
  }

  def main(args: Array[String]): Unit = {
    println(Dog.LEG_NUM)
  }
}

在单例对象中定义成员方法

object demo01 {
  object PrintUtil {
    def printSpliter() = {
      print("-" * 10)
    }
  }

  def main(args: Array[String]): Unit = {
    PrintUtil.printSpliter()
  }
}

工具类案例

import java.text.SimpleDateFormat
import java.util.Date

object demo01 {
  object DateUtils {
    val s = new SimpleDateFormat("yyyy-MM-dd HH:mm")

    def format(date:Date) = s.format(date)
  }

  def main(args: Array[String]): Unit = {
    println(DateUtils.format(new Date()))
  }
}

main方法

  • main方法是静态的,必须放在一个单例对象中
  • 除了使用main方法,还可以使用App Trait来定义入口
object demo01 extends App {
  println("hello world")
}

伴生对象

  • 有一些类,既有实例成员又有静态成员,可以使用伴生对象来实现
  • 一个object和class具有同样的名字,则个object称为伴生对象,这个类称为伴生类
  • 伴生对象和伴生类必须要同名
  • 伴生对象和伴生类在同一个scala源文件中
  • 伴生对象和伴生类可以互相访问private属性

伴生对象

object demo01 {
  class CustomerService {
    def save() = {
      println(s"${CustomerService.SERVICE_NAME} + 保存客户")
    }
  }

  //CustomerService的伴生对象
  object CustomerService {
    private val SERVICE_NAME = "CustomerService"
  }

  def main(args: Array[String]): Unit = {
    val service = new CustomerService
    service.save()
  }
}

private[this]访问权限

  • 如果某个成员的权限设置为private[this],表示只能在当前类中访问,伴生对象也不能访问
object demo01 {
  class Person(private[this] var name:String, var age:Int)

  object Person {
    def printPerson(person: Person) = {
      println(person.age)
    }
  }

  def main(args: Array[String]): Unit = {
    val person = new Person("zhangsan", 20)
    Person.printPerson(person)
  }
}

伴生对象 apply方法

object demo01 {
  class Person(var name:String = "", var age:Int = 0)

  object Person {
    //定义apply方法,接收两个参数
    def apply(name:String, age:Int) = new Person(name, age)
  }

  def main(args: Array[String]): Unit = {
    //使用伴生对象名称来创建对象
    val zhangsan = Person("zhangsan", 20)
    println(zhangsan.name)
    println(zhangsan.age)
  }
}

继承(extends)

单例对象继承

object demo01 {
  class Person {
    private var name = "super"

    def getName = this.name
  }

  object Student extends Person

  def main(args: Array[String]): Unit = {
    println(Student.getName)
  }
}

override 和 super

  • 使用override来重写一个val字段
  • 使用super关键字来访问父类的成员方法
object demo01 {
  class Person {
    val name = "super"
    def getName = this.name
  }

  class Student extends Person {
    //重写val字段
    override val name:String = "child"

    //重写getName方法
    override def getName: String = "hello " + super.getName
  }

  def main(args: Array[String]): Unit = {
    println(new Student().name)
    println(new Student().getName)
  }
}

类型判断

  • isInstanceOf判断对象是否为指定类的对象
  • asInstanceOf将对象转换为指定类型
object demo01 {
  class Person
  class Student extends Person

  def main(args: Array[String]): Unit = {
    val s:Person = new Student

    if(s.isInstanceOf[Person]){
      val s1 = s.asInstanceOf[Student]
      println("是Person类型")
    } else {
      println("是Student类型")
    }
  }
}

getClass 和 classOf

  • isInstanceOf只能判断对象是否为指定类及其子类的对象
  • 而不能精确的判断出对象就是指定类的对象
  • 可以使用getClass和classOf精确判断
object demo01 {
  class Person
  class Student extends Person

  def main(args: Array[String]): Unit = {
    val s:Person = new Student

    println(s.getClass == classOf[Person])
    println(s.getClass == classOf[Student])
  }
}

抽象类

抽象类

object demo01 {
  //定义形状抽象类
  abstract class Shape {
    def area:Double
  }
  //创建正方形类
  class Square(var length: Double) extends Shape {
    override def area: Double = length * length
  }
  //创建圆形类
  class Circle(var radius:Double) extends Shape {
    override def area: Double = Math.PI * radius * radius
  }

  def main(args: Array[String]): Unit = {
    val square = new Square(2)
    val circle = new Circle(2)

    println(square.area)
    println(circle.area)
  }
}

抽象字段

  • 没有初始化的成员变量就是抽象的
object demo01 {
  abstract class Person {
    val WHO_AM_I:String
  }

  class Student extends Person {
    override val WHO_AM_I: String = "学生"
  }

  class Policeman extends Person {
    override val WHO_AM_I: String = "警察"
  }

  def main(args: Array[String]): Unit = {
    val student = new Student
    val policeman = new Policeman

    println(student.WHO_AM_I)
    println(policeman.WHO_AM_I)
  }
}

匿名内部类

object demo01 {
  abstract class Person {
    def sayHello
  }

  def main(args: Array[String]): Unit = {
    val p = new Person {
      override def sayHello: Unit = println("这是一个匿名内部类")
    }
    p.sayHello
  }
}

特质(trait)

  • scala中没有java中的接口interface,替代的是特质trait

特质作为接口使用

object demo01 {
  trait MessageSender {
    def sender(msg:String)
  }
  trait MessageReceive {
    def receive():String
  }

  class MessageWorker  extends MessageSender with MessageReceive {
    override def sender(msg: String): Unit = println(s"发送消息:$msg")
    override def receive(): String = "接收到了消息"
  }

  def main(args: Array[String]): Unit = {
    val worker = new MessageWorker
    worker.sender("hello world")
    println(worker.receive())
  }
}
object demo01 {
  trait Logger {
    def log(message:String)
  }

  object ConsoleLogger extends Logger {
    override def log(message: String): Unit = println("控制台消息:" + message)
  }

  def main(args: Array[String]): Unit = {
    ConsoleLogger.log("hello world")
  }
}

特质中定义具体方法

object demo01 {
  trait Logger {
    def log(msg:String) = println(msg)
  }

  class UserService extends Logger {
    def add() = log("hello world")
  }

  def main(args: Array[String]): Unit = {
    val service = new UserService
    service.add()
  }
}

特质定义具体字段和抽象字段

object demo01 {
  trait Logger {
    val format = new SimpleDateFormat("yyyy-MM-dd HH:mm")
    def log(msg:String)
  }

  class ConsoleLogger extends Logger {
    override def log(msg: String): Unit = {
      val info = s"${format.format(new Date())}:控制台消息:${msg}"
      println(info)
    }
  }

  def main(args: Array[String]): Unit = {
    val logger = new ConsoleLogger
    logger.log("hello world")
  }
}

实现模板模式

object demo01 {
  trait Logger {
    def log(msg:String)
    def info(msg:String) = log("INFO" + msg)
    def warn(msg:String) = log("WARN" + msg)
  }

  class ConsoleLogger extends Logger {
    override def log(msg: String): Unit = println(msg)
  }

  def main(args: Array[String]): Unit = {
    val logger = new ConsoleLogger
    logger.info("信息日志")
    logger.warn("警告日志")
  }
}

对象混入trait

  • 给一个对象添加一些额外的行为
object demo01 {
  trait Logger {
    def log(msg:String) = println(msg)
  }

  class UserService

  def main(args: Array[String]): Unit = {
    val service = new UserService with Logger
    service.log("混入了log")
  }
}

调用链

56 Scala面向对象

object demo01 {
  trait HandlerTrait {
    def handle(data:String) = println("处理数据...")
  }

  trait DataValidHandler extends HandlerTrait {
    override def handle(data: String): Unit = {
      println("验证数据...")
      super.handle(data)
    }
  }

  trait SignatureValidHandlerTrait extends HandlerTrait {
    override def handle(data: String): Unit = {
      println("校验签名...")
      super.handle(data)
    }
  }

  class PayService extends DataValidHandler with SignatureValidHandlerTrait {
    override def handle(data: String): Unit = {
      println("准备支付...")
      super.handle(data)
    }
  }

  def main(args: Array[String]): Unit = {
    val service = new PayService
    service.handle("支付参数")
  }
}

trait构造机制

  • trait也有构造代码,但是和类不一样,特质不能有构造器参数
  • 每个特质只有一个无参构造器
  • 一个类继承另一个类,以及多个trait,当创建该类的实例时,它的构造顺序如下
    • 先执行父类的构造器
    • 从左到右依次执行trait的构造器
    • 如果trait有父trait,先构造父trait
    • 如果多个trait有同样的父trait,则只初始化一次
    • 执行子类构造器

trait继承class

  • trait也可以继承class,特质会将class中的成员都继承下来
object demo01 {
  class MyUtil {
    def printMessage(msg:String) = println(msg)
  }

  trait Logger extends MyUtil {
    def log(msg:String) = printMessage("Logger:" + msg)
  }

  class Person extends Logger {
    def sayHello() = log("hello")
  }

  def main(args: Array[String]): Unit = {
    val person = new Person
    person.sayHello()
  }
}
上一篇:C# .NET Framework 3.5 下 Task 与 EventWaitHandle 的简单例子


下一篇:Dubbo-链路追踪(skywalking)