类(class)和包

第5章 类和包

5.1 简单类和无参方法

在Scala中,类并不声明public;一个源文件中可以包含很多类,并且可以都是public级别

在使用public级别的对类时,直接实例化对象就行了

class Course(val courseName: String,var courseNum: Int) {
        var desc: String = "Scala 编程"
}

在调用无参方法时,()可写可不写

5.2 带getter和setter的属性

定义字段为私有的,则getter和setter方法也是私有的
定义 var 属性,默认会生成getter和 setter方法
定义 val 属性 默认生成getter方法
如果不需要任何getter或setter,可以将字段声明为private[this]

5.3对象私有字段

类的方法只能访问当前对象的字段,而不能访问该类的其他对象的字段

5.4 Bean属性

当你将Scala字段标注为@BeanProperty时,这样的方法会自动生成

import scala.reflect.BeanProperty
class Person{
	@BeanProperty var name: String = _
}

将会生成四个方法:name、name_、getname、setName

5.5 构造函数

构造函数(primary constructor & auxiliary constructor)

主构造器紧跟在类名后边,主构造器中参数会被编译成字段、主构造器会执行类中所有语句。

主构造器中参数如果不带 val 或者 var 相当于private[this]

附属构造器用this 命名,附属构造器必须调用存在的构造器

5.6 嵌套类

在类中嵌套类

实例化内部类时只需:new 外部类名.内部类名

5.7 继承

Scala类的继承层级

image-20200113173604922

5.7.1 继承(extends)

在定义时给出子类需要而超类没有的字段和方法,或重写超类的方法

如果不想类、方法或字段被继承,可声明为final

5.7.2 继承(override )

继承的字段方法必须写override 关键字否则语法错误

重写父类⽅方法(override def)

重写字段(override val , override var)

isInstanceOf方法:用于测试某个对象是否属于某个给定的类

asInstanceOf方法:将引用转换为子类的引用

5.8 案例类(case class)

本质上case class是个语法糖,对你的类构造参数增加了getter访问,还有toString, hashCode, equals 等方法

Case class实现了一个伴生对象,这个伴生对象里定义了apply方法和 unapply 方法

定义简单的case class B,反编译其生成的class

编译器对case类混入了Product特质,编译器对case类增加了copy方法

编译器对case类实现了equals/hashCode/toString等方法

伴生对象中最重要的方法是 unapply 这个方法是在进行构造器模式匹配时的关键。

伴生对象中apply方法则为创建对象提供方便,相当于工厂方法

伴生对象继承了AbstractFunction,允许接收 Tuple 作为参数构造

从case类的设计目的来看,最重要的是提供构造器模式匹配(且构造时的参数,与解构的结果一致),另外case类可看作是数据对象,不可变的数据对象。

case class A(a: Int, b: Int)
     A.tupled
     val t  = (100,100)
     A.tupled(t)

5.9 抽象类(abstract class)

类的一个或者多个方法没有没完整的定义

声明抽象方法不需要加abstract关键字,只需要不写方法体

子类重写父类的抽象方法时不需要加override

父类可以声明抽象字段(没有初始值的字段)

子类重写父类的抽象字段时不需要加override

5.9 抽象

抽象类、字段、方法都是用abstract来标记。

抽象字段、方法必须写在抽象类中,但抽象类中不一定包含抽象方法或字段

5.10 特质(trait)

目的:解决多继承的问题

Trait是字段和行为的集合

Trait 是可以有具体实现的接口(和Java不同)

类可以实现任意数量的特质;类/trait 通过with 关键字一个类可以扩展多个特质
第一混入特质用extends

混入类中

从左到右被实例化(超类->所有特质构造在超类之后,类构造器之前->特质由左到右->有父特质,父特质先构造,父特质只会构造一次)

特质不能有构造器参数,每个特质都有一个无参数的构造器

特质中的字段可以是抽象的也可以是具体的
有具体值就是具体的

特质中的每一个具体字段,使用该特质的类都会获得一个字段与之对应

这些字段不是继承的它们只是简单的被加入到子类中,一个类在JVM中只能有一个超类,因此来自特质的字段不能以相同方式继承,由于这个原因,从特质“继承”来的字段被直接加入到子类中(可以查看字节码文件看到这种关系)。

特质中的抽象字段在具体子类中必须被重写,不需要写override

特质的构造顺序
首先调用超类构造器混入类中
特质构造器在超类构造器之后、类构造器之前执行
每个特质中父特质先被构造
多个特质共有一个父特质,该父特质只构造一次
所有特质构造完毕,子类构造
特质的构造顺序从左向右跟线性化的顺序相反

select关键字

(1) 修饰的trait,class只能在当前文件里面被继承
(2) 用sealed修饰这样做的目的是告诉Scala 编译器在检查模式匹配的时候,让 Scala 知道这些case的所有情况,scala就能够在编译的时候进行检查,看你写的代码是否有没有漏掉什么没case到,减少编程的错误。

扩展类的特质

特质也可以扩展类,这个类将自动成为所有混入该特质的超类

image-20200113204022314

自生类型

当特质扩展类时编译器能够确保所有混入该特质的类都以这个类为超类

自身类型也能做到相同的效果,特质并没有扩展Exception,而是有一个自身类型,在特质的方法中我们可以调用该自身方法的任何方法;自类当然也可以是复合类型

5.11 包

Scala 的包和Java 中的包目的相同,管理大型程序中的名称,java 中有个名称叫做完全限定名,是指包名+类名的组合名称,在类路径中唯一标识一个类,避免重复。

Scala的包支持嵌套,你可以访问上层作用域中的名称

包语句可以包含一个“串”(路径区段)

5.12 引入

让你在使用时可以使用更短的名称而不是原来较长的名称

包引入通过import 关键字,在程序的任意位置引入

import 包名._: 可以引入该包下所有的成员

import 包名.{成员名, 成员名,···} 可以引入该包下指定的成员

每个Scala 程序都隐式的引入

​ import java.lang._

​ import scala._

​ import Predef._

重命名 import java.util.{HashMap => JavaHashMap}

protected修饰的成员只能被子类访问,且对类所属包是不可见的

protected[this]将访问权限定在当前的对象

posted @   昵称已经被使用  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
点击右上角即可分享
微信分享提示