类(class)
类是对象的模板,通过构造类,能够使用new关键字声明一系列同结构的对象
对象(object)
除了使用类构造对象模板,可以使用object构造单例对象
继承
继承是类的拓展
特质
一个类只能继承自一个父类,但可以由多个特质拓展而成
类是对象的模板,通过构造类,能够使用new关键字声明一系列同结构的对象
对象(object)
除了使用类构造对象模板,可以使用object构造单例对象
继承
继承是类的拓展
特质
一个类只能继承自一个父类,但可以由多个特质拓展而成
类定义
类成员主要包括字段(val跟var)、方法与函数(def),但Scala禁止使用同样的名称命名字段和方法,即既声明一个value字段,又声明一个value方法是不允许的
类成员可见性有两种,private(私有)跟public(公有),private需要声明,public无需额外声明
类声明后利用new声明对象
类成员可见性有两种,private(私有)跟public(公有),private需要声明,public无需额外声明
类声明后利用new声明对象
调用无参方法时可以不带(),若类中声明无参方法时不带(),实际调用也不可带()。
getter、setter方法
Scala对每个类中的字段都提供getter和setter方法
对于公有字段来说,其getter和setter方法同样是共有的,对于私有字段来说,则是私有的
var声明的字段带有getter和setter方法(读写)
val声明的字段自带有getter方法(只读)
主构造器
对于公有字段来说,其getter和setter方法同样是共有的,对于私有字段来说,则是私有的
var声明的字段带有getter和setter方法(读写)
val声明的字段自带有getter方法(只读)
主构造器
每个类都有主构造器,且与类定义交织在一起
主构造器的参数直接放置在类名之后
主构造器的参数被编译成字段,并在构造对象时初始化传入
一个类若没有显式定义主构造器自动拥有一个无参主构造器
主构造器的参数一般有四种:
(1)value:String
生成对象私有字段,对象中没有方法使用value,则没有该字段
(2)private val/var value:String
私有字段,私有的getter/setter方法
(3)val/var value:String
私有字段,公有的getter/setter方法
(4) @BeanProperty val/var value:String
私有字段,公有的Scala和JavaBean的getter/setter方法
主构造器的参数直接放置在类名之后
主构造器的参数被编译成字段,并在构造对象时初始化传入
一个类若没有显式定义主构造器自动拥有一个无参主构造器
主构造器的参数一般有四种:
(1)value:String
生成对象私有字段,对象中没有方法使用value,则没有该字段
(2)private val/var value:String
私有字段,私有的getter/setter方法
(3)val/var value:String
私有字段,公有的getter/setter方法
(4) @BeanProperty val/var value:String
私有字段,公有的Scala和JavaBean的getter/setter方法
主构造器私有,只能通过辅助构造器构造对象
辅助构造器
Scala类能有任意多的辅助构造器
辅助构造器的名称为this,在类中定义
辅助构造器必须以一个主构造器或其他已定义的辅助构造器调用开始
嵌套类
辅助构造器的名称为this,在类中定义
辅助构造器必须以一个主构造器或其他已定义的辅助构造器调用开始
嵌套类
Scala允许任何语法结构中镶嵌任何语法结构,因此能在类中定义类
对于同一个外部类,不同实例下的内部类是不同的
内部类中可以调用外部类的成员,利用外部类.this或指针实现
Scala对象
单例对象
伴生对象
扩展类和特质
构造一个扩展了指定类和特质的类的对象,同时拥有对象定义中给出的所有特性
apply方法
伴生对象
扩展类和特质
构造一个扩展了指定类和特质的类的对象,同时拥有对象定义中给出的所有特性
apply方法
单例对象
object语法定义了某个类的单个实例
对象的构造器在该对象第一次被使用时调用
object语法结构与class大致相同,除了object不能提供构造器参数
通常使用单例对象的环境:
作为存放工具函数或常量的地方
共享单个不可变实例
利用单个实例协调某个服务
伴生对象
对象的构造器在该对象第一次被使用时调用
object语法结构与class大致相同,除了object不能提供构造器参数
通常使用单例对象的环境:
作为存放工具函数或常量的地方
共享单个不可变实例
利用单个实例协调某个服务
伴生对象
当一个单例对象存在同名类的时候,称为伴生对象
class HELLOWORLD{...}
objectHELLOWORLD{...}
类和其伴生对象可以互相访问私有属性,但必须存在同一个源文件中
类的伴生对象可以被访问,但并不在作用域中
class HELLOWORLD{...}
objectHELLOWORLD{...}
类和其伴生对象可以互相访问私有属性,但必须存在同一个源文件中
类的伴生对象可以被访问,但并不在作用域中
apply方法
需要构造有参数需求的伴生对象时,可定义并使用apply方法
Scala继承
拓展
extends是Scala中实现继承的保留字
子类继承了超类所有非私有成员
子类能重写超类的成员(具有相同名称和参数)
单例对象同样能从类中继承,与类的继承语法相同
子类能重写超类的成员(具有相同名称和参数)
单例对象同样能从类中继承,与类的继承语法相同
重写
override保留字实际使用类似与private,声明这个保留字后的定义、声明是对超类的重写,因此,其也可以写在类定义的参 数中
子类的重写或修改Scala会检查其超类,但是,超类的修改并不会检查其子类
重写包括字段和方法,但参数不同的方法可以不重写
规则:
重写def
用val :利用val能重写超类用没有参数的方法(getter)
用def:子类的方法与超类方法重名
用var:同时重写getter、setter方法,只重写getter方法报错
重写val
用val:子类的一个私有字段与超类的字段重名,getter方法重写超类的getter方法
重写var
用var:且当超类的var是抽象的才能被重写,否则超类的var都会被继承
子类中,def只能重写超类的def,val能重写超类的val或不带参数的def,var只能重写超类中抽象的var或者超类的gette r/setter对
重写包括字段和方法,但参数不同的方法可以不重写
规则:
重写def
用val :利用val能重写超类用没有参数的方法(getter)
用def:子类的方法与超类方法重名
用var:同时重写getter、setter方法,只重写getter方法报错
重写val
用val:子类的一个私有字段与超类的字段重名,getter方法重写超类的getter方法
重写var
用var:且当超类的var是抽象的才能被重写,否则超类的var都会被继承
子类中,def只能重写超类的def,val能重写超类的val或不带参数的def,var只能重写超类中抽象的var或者超类的gette r/setter对
抽象
不能被实例的类叫做抽象类
抽象类的某个或某几个成员没有被完整定义,这些没有被完整定义的成员称为抽象方法或抽象字段
用abstract保留字标记抽象类
只要类中有任意一个抽象成员,必须使用abstract标记
重写抽象方法、抽象字段不需要使用override保留字
抽象类的某个或某几个成员没有被完整定义,这些没有被完整定义的成员称为抽象方法或抽象字段
用abstract保留字标记抽象类
只要类中有任意一个抽象成员,必须使用abstract标记
重写抽象方法、抽象字段不需要使用override保留字
保护
当一个类不希望被继承、拓展时,可在类声明前加上final保留字
当一个类的某些成员不希望被重写时,可以在成员声明前加上final保留字
当超类中的某些成员需要被子类继承,又不想对子类以外成员可见时,在成员声明前加上protected保留字
protected[this],将访问权限定于当前对象,类似于private[this]
类中protected的成员对其子类可见,对其超类不可见
当一个类的某些成员不希望被重写时,可以在成员声明前加上final保留字
当超类中的某些成员需要被子类继承,又不想对子类以外成员可见时,在成员声明前加上protected保留字
protected[this],将访问权限定于当前对象,类似于private[this]
类中protected的成员对其子类可见,对其超类不可见
构造
子类构造器的运行在超类构造器运行之后
在超类的构造器中调用的成员被子类重写后,返回值可能不正确
提前定义:在超类的构造器运行之前初始化子类的字段
把需要提前定义的语句块放在extends与超类之间,并后接with保留字
Scala特质
一旦特质被定义了,就可以混入到类中
当要混入多个特质时,利用with保留字
在超类的构造器中调用的成员被子类重写后,返回值可能不正确
提前定义:在超类的构造器运行之前初始化子类的字段
把需要提前定义的语句块放在extends与超类之间,并后接with保留字
Scala特质
不支持多重继承
Scala不支持多重继承,取而代之的是特质
一个子类只能拥有一个超类,一个超类能拥有多个子类
若一个子类继承自不同的超类,不同的超类中同名成员子类不知如何处理
多重继承产生菱形继承问题
解决多重继承可能导致的问题消耗的资源远比多重继承产生的价值高
Scala使用特质达到类似多重继承的效果
一个类可以扩展自一个或多个特质,一个特质可以被多个类扩展
特质能限制被什么样的类所扩展
一个子类只能拥有一个超类,一个超类能拥有多个子类
若一个子类继承自不同的超类,不同的超类中同名成员子类不知如何处理
多重继承产生菱形继承问题
解决多重继承可能导致的问题消耗的资源远比多重继承产生的价值高
Scala使用特质达到类似多重继承的效果
一个类可以扩展自一个或多个特质,一个特质可以被多个类扩展
特质能限制被什么样的类所扩展
特质使用
特质是Scala里代码复用的基础单元,封装了方法和字段的定义
类似于java中的接口,但不完全一样
特质的定义使用保留字trait,具体语法与类定义相似,除了不能拥有构造参数一旦特质被定义了,就可以混入到类中
当要混入多个特质时,利用with保留字
所有JAVA接口都能当做是特质使用在Scala中
特质的成员可以是抽象的,而且,不需要使用abstract声明
同样的,重写特质的抽象方法无需给出override
但是,多个特质重写同一个特质的抽象方法需给出override
除了在类定义中混入特质以外,还可以在特质定义中混入特质以及在对象构造时混入特质
同样的,重写特质的抽象方法无需给出override
但是,多个特质重写同一个特质的抽象方法需给出override
除了在类定义中混入特质以外,还可以在特质定义中混入特质以及在对象构造时混入特质
特质构造
特质的构造是有顺序的,从左到右被构造
构造器按如下顺序构造:
(1)超类
(2)父特质
(3)第一个特质
(4)第二个特质(父特质不重复构造)
(5)类
如果class A extends B1 with B2 with B3....
那么,串接B1、B2、B3...等特质,去掉重复项且右侧胜出
构造器按如下顺序构造:
(1)超类
(2)父特质
(3)第一个特质
(4)第二个特质(父特质不重复构造)
(5)类
如果class A extends B1 with B2 with B3....
那么,串接B1、B2、B3...等特质,去掉重复项且右侧胜出
特质应用
(1)特质的一个主要应用方面在于接口,根据类已有的方法自动为类添加方法
利用特质实现富接口:
构造一个具有少量抽象方法和大量基于抽象方法的具体方法的特质
那么,只要把特质混入类中,通过类重写抽象方法后,类便自动获得大量具体方法
(2)特质的另一个应用方面在于:为类提供可堆叠的改变(super保留字)
当为类添加多个互相调用的特质时,从最后一个开始进行处理
在类中super.foo()这样的方法调用是静态绑定的,明确是调用它的父类的foo()方法
在特质中写下了super.foo()时,它的调用是动态绑定的。调用的实现将在每一次特质被混入到具体类 的时候才被决定
因此,特质混入的次序的不同其执行效果也就不同
利用特质实现富接口:
构造一个具有少量抽象方法和大量基于抽象方法的具体方法的特质
那么,只要把特质混入类中,通过类重写抽象方法后,类便自动获得大量具体方法
(2)特质的另一个应用方面在于:为类提供可堆叠的改变(super保留字)
当为类添加多个互相调用的特质时,从最后一个开始进行处理
在类中super.foo()这样的方法调用是静态绑定的,明确是调用它的父类的foo()方法
在特质中写下了super.foo()时,它的调用是动态绑定的。调用的实现将在每一次特质被混入到具体类 的时候才被决定
因此,特质混入的次序的不同其执行效果也就不同