Scala中的类和对象

Scala是一种函数式的面向对象语言, 它也是支持面向对象编程思想的,也有类和对象的概念。我们依然可以基于Scala语言来开发面向对象的应用程序。

创建类和对象:

Scala中创建类和对象可以通过class和new关键字来实现. 用class来创建类, 用new来创建对象.

代码示例:

创建一个Person类,并创建它的对象, 然后将对象打印到控制台上.

package test4

object Test3 {
  class Person {}

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

简写方式

  • 如果类是空的,没有任何成员,可以省略{}

  • 如果构造器的参数为空,可以省略()

package test4

object Test3 {
  class Person

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

}

定义和访问成员变量

  • 在类中使用var/val来定义成员变量

  • 对象可以通过对象名.的方式来访问成员变量

代码示例:

  1. 定义一个Person类,包含一个姓名和年龄字段

  2. 创建一个名为"张三"、年龄为23岁的对象

  3. 打印对象的名字和年龄

  class Person {
    var name:String = ""
    var age:Int = 0
  }

  def main(args: Array[String]): Unit = {
    var person = new Person()
    person.name = "张三"
    person.age = 23
    println(person.name)
    println(person.age)
  }

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

scala中有一个更简洁的初始化成员变量的方式,可以让代码看起来更加简洁, 更优雅.

代码案例:

package test5

object test1 {
  class Person {
    var name: String = _
    var age: Int = _
  }

  def main(args: Array[String]): Unit = {
    var p = new Person
    p.name = "zhangsan"
    p.age = 18
    println(p.name, p.age)
  }
}

定义和访问成员方法

类可以有自己的行为,scala中也可以通过定义成员方法来定义类的行为。

格式

def 方法名(参数1:数据类型, 参数2:数据类型): [return type] = {
    //方法体
}
  • 返回值的类型可以不写, 由Scala自动进行类型推断.

代码示例: 

package test5

object test2 {
  class Customer {
    var name: String = _
    var age: Int = _

    def printHello(msg: String) = {
      println(msg)
    }
  }

  def main(args: Array[String]): Unit = {
    var customer = new Customer
    customer.name = "张三"
    customer.age = 20
    println(customer.name, customer.age)
    customer.printHello("hello")
  }
}

访问权限修饰符

  • 和Java一样,scala也可以通过访问修饰符,来控制成员变量和成员方法是否可以被外界访问。
  • Scala中的权限修饰符只有: private, private[this], protected, 默认这四种.

代码示例:

package test5

object test3 {
  class Customer {
    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 printHello() = {
      println("hello")
    }
  }

  def main(args: Array[String]): Unit = {
    var customer = new Customer
    customer.setName("zhangsan")
    customer.setAge(20)
    println(customer.getName(), customer.getAge())

    //    customer.printHello()   外界无法访问这个函数
  }

}

类的构造器

当创建对象的时候,会自动调用类的构造器。之前使用的都是默认构造器,接下来我们要学习如何自定义构造器。

  • 主构造器

  • 辅助构造器

主构造器

格式:

class 类名(var/val 参数名:类型 = 默认值, var/val 参数名:类型 = 默认值){
    //构造代码块
}

代码示例:

  1. 定义一个Person类,通过主构造器参数列表定义姓名和年龄字段,并且设置它们的默认值为张三, 23

  2. 在主构造器中输出"调用主构造器"

  3. 创建"李四"对象(姓名为李四,年龄为24),打印对象的姓名和年龄

  4. 创建"空"对象,不给构造器传入任何的参数,打印对象的姓名和年龄

  5. 创建"测试"对象,不传入姓名参数,仅指定年龄为30,打印对象的姓名和年龄

package test5

object test4 {
  class Person(var name: String = "zhangsan", var age: Int = 23) {
    println("调用主构造器")
  }

  def main(args: Array[String]): Unit = {
    var p1 = new Person()
    println(p1.name, p1.age)

    var p2 = new Person("lisi", 24)
    println(p2.name, p2.age)

    var p3 = new Person(age = 30)
    println(p3.name, p3.age)
  }
}

辅助构造器

  • 定义辅助构造器与定义方法一样,也使用def关键字来定义

  • 辅助构造器的默认名字都是this, 且不能修改.

格式:

def this(参数名:类型, 参数名:类型) {
    // 第一行需要调用主构造器或者其他构造器
    // 构造器代码
}

 代码示例:

package test5

object test5 {
  class Customer(var name: String, var address: String) {
    def this(arr: Array[String]) {
      this(arr(0), arr(1))
    }
  }

  def main(args: Array[String]): Unit = {
    var customer = new Customer(Array("zhangsan", "beijin"))
    println(customer.name, customer.address)
  }
}

单例对象

scala中是没有static关键字的,要想定义类似于Java中的static变量、static方法,就要使用到scala中的单例对象了, 也就是object.

  • 1. 在object中定义的成员变量类似于Java中的静态变量, 在内存中都只有一个对象.
  • 2. 在单例对象中, 可以直接使用`单例对象名.`的形式调用成员.

定义单例对象

格式:

object 单例对象名{ }			//定义一个单例对象.

代码案例:

package test5

object test6 {
  object Dog {
    val leg_num = 4

    def showLeg() = {
      println("大黄有四条腿")
    }
  }

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

定义伴生对象

  • 一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类
  • 伴生对象必须要和伴生类一样的名字
  • 伴生对象和伴生类在同一个scala源文件中
  • 伴生对象和伴生类可以互相访问private属性
package test5

object test7 {
  class Generals {
    def toWar = println(s"武将拿着${Generals.armsName}武器, 上阵杀敌!")
  }

  object Generals {
    private var armsName = "青龙偃月刀"
  }

  def main(args: Array[String]): Unit = {
    var generals = new Generals
    generals.toWar
  }
}

private[this]访问权限

  • 定义一个Person类,包含一个name字段, 该字段用private[this]修饰

  • 定义Person类的伴生对象,定义printPerson方法

  • 测试伴生对象是否能访问private[this]权限的成员

package test5

object test8 {
  class Person(private[this] var name: String) {}

  object Person {
    def printPerson(p: Person) = println(p.name)
  }

  def main(args: Array[String]): Unit = {
    var person = new Person("张三")
    Person.printPerson(person)
  }
}

 注意: 上述代码,会编译报错。但移除掉[this]就可以访问了

apply方法

  • 在Scala中, 支持创建对象的时候, 免new的动作, 这种写法非常简便,优雅。
  • 要想实现免new, 我们就要通过伴生对象的apply方法来实现。

格式:

object 伴生对象名 {
	def apply(参数名:参数类型, 参数名:参数类型...) = new 类(...)
}

 创建对象 :

val 对象名 = 伴生对象名(参数1, 参数2...)

代码示例:

  • 定义一个Person类,它包含两个字段:姓名和年龄

  • 在伴生对象中定义apply方法,实现创建Person对象的免new操作.

  • 在main方法中创建该类的对象,并打印姓名和年龄

package test5

object test9 {
  //定义person类
  class Person(var name: String = "", var age: Int = 0)

  //定义person的伴生对象
  object Person {
    //定义apply方法,实现创建Person对象的时候免new
    def apply(name: String, age: Int) = new Person(name, age)
  }

  def main(args: Array[String]): Unit = {
    val p = Person("张三", 23)
    println(p.name, p.age)
  }
}

 

定义工具类

Scala中工具类的概念和Java中是一样的, 都是

  • 构造方法全部私有化, 目的是不让外界通过构造方法来创建工具类的对象.
  • 成员全部是静态化, 意味着外界可以通过"类名."的形式来访问工具类中的内容.
  • 综上所述, 在Scala中只有object单例对象满足上述的要求.

代码示例: 

需求:

  • 编写一个DateUtils工具类专门用来格式化日期时间

  • 定义一个方法,用于将日期(Date)转换为年月日字符串,例如:2030-10-05

  • 定义一个方法, 用于将年月日字符串转换为日期(Date).

步骤: 

  • 定义一个DateUtils单例对象

  • 在DateUtils中定义日期格式化方法(date2String)和解析字符串方法(string2Date)

  • 使用SimpleDateFormat来实现String和Date之间的相互转换

 

代码案例: 

package test5

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

object Test10 {
  object DateUtils {
    var sdf: SimpleDateFormat = null

    def date2String(date: Date, template: String): String = {
      sdf = new SimpleDateFormat(template)
      sdf.format(date)
    }

    def string2Date(dateString: String, template: String) = {
      sdf = new SimpleDateFormat(template)
      sdf.parse(dateString)
    }
  }

  def main(args: Array[String]): Unit = {
    val s = DateUtils.date2String(new Date(), "yyyy-MM-dd")
    println("格式化日期: " + s)

    val d = DateUtils.string2Date("2023年5月21日", "yyyy年MM月dd日")
    println("解析字符串: " + d)
  }

}

你可能感兴趣的:(Scala,scala,开发语言,后端)