大家好,我是百思不得小赵。


文章目录


Scala 的面向对象思想和 Java 的面向对象思想和概念是一致的,但是对应的语法有所不同。

一、Scala中的包管理

基本语法

package +

包管理的作用

  • 区分相同名字的类
  • 当类很多时,可以很好的管理类
  • 控制访问范围

包的命名

  • 命名规则:​​只能包含数字、字母、下划线、小圆点.,但不能用数字开头,也不要使用关键字。​
  • 命名规范:按照如下规则命名​​com.公司名.项目名.业务模块名​

Scala中的两种包管理方式

  • 第一种:和 Java 的包管理风格相同,每个源文件一个包,包名用​​.​​进行分隔以表示包的层级关系,包名和源文件所在路径不要求必须一致。
  • 第二种:嵌套的风格表示层级关系​​{}​

举个栗子:

package com{
// 外层包定义单例对象
object Outer{
var out: String="out"
def main(args: Array[String]): Unit = {
println(Inner.in)
}
}

package zhao{
package scala{
// 内层包中的对象
object Inner{
val in: String="Inner"

def main(args: Array[String]): Unit = {
println(Outer.out)
Outer.out="ourter"
println(Outer.out)
}
}
}
}
}

嵌套风格的好处:

  • 一个源文件中可以声明多个 package
  • 子包中的类可以直接访问父包中的内容,而无需导包

包对象

定义包对象:

package object 包名{
// 代码块
}
  • Scala 中可以为每个包定义一个同名的包对象,定义在包对象中的成员,作为其对应包下所有 class 和 object 的共享变量,可以被直接访问。
  • 定义当前包共享的属性和方法。
  • 必须为同一个包下面的单例对象或者类才能访问到

导入包

  • ​import java.util._​​​ 导入包​​util​​中的所有成员
  • ​import java.util.{ArrayList=>JL}​​​ 引入​​util​​​下的​​ArrayList​​​类起别名为​​JL​
  • ​import java.util.{HashSet, ArrayList}​​​ 导入​​util​​中的多个类
  • ​import java.util.{ArrayList =>_,_}​​ 屏蔽类
  • ​new _root_.java.util.HashMap​​ 导入包的绝对路径

Scala中导入了三个默认的包:

  • ​import java.lang._​
  • ​import scala._​
  • ​import scala.Predef._​

二、类和对象

定义:

[修饰符] class 类名 {
// 定义属性
[修饰符] var/val name: 类型名= _
// 定义方法
[修饰符] 方法名(args: ArgsType): RetType = {

}
}
  • 在Java里面,声明类需要使用​​public​​​进行修饰,类名和文件名必须保持一致。一个​​.java​​​文件 有一个​​public​​ 类。
  • Scala中没有​​public​​​关键字,默认就是公共的,一个​​.scala​​​ 中可以写多个类。声明类时不能加​​public​​,会报错。类名不要求和文件名一致。
  • 成员需要Java Bean规范的​​getter​​​和​​setter​​​方法的话可以加​​@BeanProperty​​相当于自动创建,不需要显式写出。
  • 给成员属性赋初始值使用​​_​​​,值类型的值​​0​​​,引用则是​​null​​​。定义常量的话不能用​​_​​。

访问权限

  • Java 中,访问权限分为:​​public​​​,​​private​​​,​​protected​​​ 和​​默认​
  • Scala 中属性和方法的默认访问权限为​​public​​,但 Scala 中无 public 关键字,不用显式声明。
  • ​private​​ 为私有权限,只在类的内部和伴生对象中可用。
  • ​protected​​ 为受保护权限,同类、子类可以访问,同包无法访问。
  • ​private[包名]​​ 增加包访问权限,包名下的其他类也可以使用

创建对象

val 或者 var 对象名 [: 类型] = new 类型()
  • val 修饰对象,不能改变对象的引用(内存地址),可以改变对象属性的值。
  • var 修饰对象,可以修改对象的引用和修改对象的属性值

构造器

Scala 构造对象也需要调用构造方法,构造器包括​​主构造器​​​和​​辅助构造器​​。

class 类名(形参列表) { // 主构造器
// 类体
def this(形参列表) { // 辅助构造器

}
def this(形参列表) { //辅助构造器可以有多个...

}
}

举个栗子:

object Test05_Constructor {
def main(args: Array[String]): Unit = {
val student = new Student1()
student.Student1()

val student1 = new Student1("王五")
val student3 = new Student1("李四",21)

}
}

// 无参的主构造器
class Student1(){
var name: String= _
var age: Int = _
println("1.主构造方法被调用 ")

// 声明辅助构造方法 必须直接或间接的调用主构造器
def this(name: String){
// 调用主构造器
this()
println("2.辅助构造方法 一 ")
this.name = name
println(s"name: $name age: $age")
}
def this(name: String,age: Int){
// 间接调用主构造器
this(name)
println("3.辅助构造方法 二 ")
this.age = age
println(s"name: $name age: $age")
}

def Student1(): Unit = {
println("一般方法被调用,不是构造方法!!")
}
}

特点说明:

  • 主构造器在类定义上,创建对象最先调用的构造器。
  • 辅助构造器用​​this​​定义,可以有多个。
  • 辅助构造方法不能直接构建对象,必须直接或者间接调用主构造方法
  • 构造器调用其他另外的构造器,要求被调用构造器必须提前声明。
  • 定义和类同名的方法,就是一个普通方法。

主构造器参数说明

  • 主构造器函数的形参包括三种类型:​​未用任何修饰​​​、​​var​​​ 修饰、​​val​​ 修饰
  • 不加参数列表相当于为空,​​()​​可以省略。
  • 未用任何修饰符修饰,这个参数就是一个局部变量
  • ​var​​​ 修饰参数,作为类的成员属性使用,可以修改,​​val​​ 修饰参数,作为类只读属性使用,不能修改

举个栗子:

class Student2(var name: String,var age: Int)

//主构造器 无修饰
class Student3( name: String, age: Int){
def printInfo(): Unit ={
println(s"student3: name = $name, age = ${age}")
}
}

class Student4(val name: String,val age: Int)

class Student5(var name: String,var age: Int){
var school: String = _
def this( name: String, age: Int,school: String){
this(name,age)
this.school = school
}

def printInfo(): Unit ={
println(s"student5: name = $name, age = $age,school = $school")
}
}

三、面向对象三大特性

封装

  • Java中的封装:将属性私有化,提供​​getter​​​和​​setter​​,用于赋值和获取值。
  • Scala中的公有属性,底层实际为​​private​​​,并通过get方法​​obj.field()​​​和set方法o​​bj.field_=(value)​​​对其进行操作。所以scala不推荐设置为private。如果需要和其他框架互操作,必须提供Java Bean规范的getter和setter的话可以加​​@scala.beans.BeanProperty​​注解。
class Student {
// 定义属性
private val name: String = "lisi"
// 把对应的符合JavaBean规范的getter和setter创建出来
@BeanProperty
var age: Int = _
var sex: String = _
}

继承

如何定义?

class 子类名 extends 父类名 { 类体 }
  • 子类继承父类的属性和方法。
  • Scala和Java一样都是单继承的。
  • 继承的调用顺序,父类为先,子类在后。

举个栗子:

class Person(){
var name: String = _
var age: Int = _
println("1.父类的主构造器调用")

def this(name: String,age: Int){
this()
println("2.父类的辅助构造器被调用")
this.name = name
this.age = age
}

def printInfo(): Unit ={
println(s"Person: $name $age")
}
}

// 默认调用Person的无参主构造器
class Student(name: String,age: Int) extends Person(name ,age ){
var stuNo: String = _
println("3.子类的主构造器调用")

def this(name: String,age: Int,stuNo: String){
this(name,age)
this.stuNo = stuNo
println("4.子类的辅助构造器调用")
}

// 重写父类的方法
override def printInfo(): Unit = {
println(s"Student: $name $age $stuNo")
}
}

多态

  • Java中的属性是静态绑定的,方法是在运行时动态绑定的。
  • Scala 中的属性和方法都是动态绑定的。
  • Scala中属性也可以被重写,使用override关键字。

举个栗子:

class Person {
val name: String = "person"
def hello(): Unit = {
println("hello person")
}
}
class Teacher extends Person {
override val name: String = "teacher"
override def hello(): Unit = {
println("hello teacher")
}
}
object Test {
def main(args: Array[String]): Unit = {
val teacher: Teacher = new Teacher()
println(teacher.name)
teacher.hello()

val teacher1:Person = new Teacher
println(teacher1.name)
teacher1.hello()
}
}

本次分享的内容到这里就结束了,希望对大家学习Scala语言有所帮助!!!

Scala 基础 (五):面向对象(上篇)_构造器