scala构造器
主构造器
1.在scala中,主构造器是和类名放在一起的,有且只有一个,与java不同,java可以有多个构造方法,多个构造方法之间可以实现重载
2.主构造器还可以通过使用默认参数,来给参数默认的值
3.在类中,没有定义在任何方法中的代码(包括成员类型),都属于主构造器的代码,且执行顺序与代码的书写的顺序是一致的
4.如果主构造器的参数使用val或者var修饰了,那么就是成员属性,否则就仅仅是一个局部变量
5.主构造器的参数必须赋值
辅助构造器
1.辅助构造器可以又多个
2.多个辅助器之间可以调用
3.辅助构造器中的参数不可以使用val/var
4.辅助构造器的第一行必须调用主构造器或者其他辅助构造器
私有构造器
1.私有构造器是针对于主构造器
2.如果声明了私有构造器,那么只能被他的伴生对象访问
3.如果主构造器设置为私有构造器,那么辅助构造器依然可以访问
class Teacher private (var name:String, val age:Int = 34) {
val id:Int = 1
var sex:String = _
private var pro:String = _
println("俺是主构造器")
//定义一个辅助构造器,def this()
//辅助构造器的参数不能使用val/var修饰符
def this(name:String,age:Int,sex:String){
//第一句话必须是先调用主构造器
this(name,age)
println("第一个辅助构造器")
this.sex=sex
}
def this(name:String,age:Int,sex:String,pro:String){
//调用第一个辅助构造器
this(name,age,sex)
println("第二个辅助构造器")
this.pro = pro
}
//打招呼方法
def sayHello() ={
//调用Teacher类中的方法
//伴生对象中可以访问伴生类额私有成员和属性
Teacher.sayHello(this.name)
}
}
object Teacher {
//打招呼方法
private def sayHello(name:String) ={
println(s"hello ${name}")
}
def main(args: Array[String]): Unit = {
val teacher = new Teacher("苍老师", 18)
teacher.sex = "女"
println(s"启蒙老师:${teacher.name},编号:${teacher.id},性别:${teacher.sex},年龄:${teacher.age}")
teacher.pro = "XX省"
val teacher2 = new Teacher("波多老师",28,"男")
//访问的是Teacher类中的打招呼方法
teacher2.sayHello()
}
}
作用域
1.默认是public
2.跟java相似
3. public:表示公共的,任意都可以访问
private:表示私有的, 表示当前类的对象都可以访问(伴生对象和伴生类依然可以访问)
private[this]:当前对象(实例)都可以访问,其他对象不能访问,连伴生对象都不能访问
private[package]:表示某个包下面可以访问,比如private[Spark],表示在Spark包下所有的类都可以访问
伴生对象
1.如果有一个class,还有一个与clas同名的object,那么就称这个object是class的伴生对象,class是object的伴生类
2. 伴生类和伴生对象必须放在一个.scala的文件中
3.伴生类和伴生对象,最大的特点就在于,相互之间可以访问private的字段
class MyGril {
private var name = "苍老师"
//输出伴生对象的name
println(MyGril.name)
}
//一个单例模式
object MyGril{
private var name = "波多老师"
//输出伴生类的name
println(new MyGril().name)
def apply(name:String) ={
println(s"女神:${name}")
}
}
object TestMyGril{
def main(args: Array[String]): Unit = {
var gril1 = MyGril("小泽老师")
var gril2 = MyGril("长泽老师")
}
}
//结果
//波多老师
//苍老师
//女神:小泽老师
//女神:长泽老师
scala中的object
1.object:相当于java的静态类,类似于java的单例模式,通常在里面放一些class里面共享的内容
2.可以将object看成一个类class,只是这个类在内存中是一个单例,且定义的object就是实例名,不需要我们自己进行实例化,运行与JVM在java中帮我们new出来了
3.第一次调用object方法时,会执行object的构造器,也就是说object内部不再方法中的代码(并且被执行一次),但是object不能定义接收参数的构造器
4.注意object的构造器只是会在第一次调用的时候执行,以后每次调用不会再次执行构造器了
5.使用场景
初始化配置文件
公共处理类(方法)
数据库的初始化
…
class StaticTest {
private def add(x:Int,y:Int) ={
x+y
}
}
//这个是单例模式的定义,和类名相同,且不带参数
object StaticTest{
//声明一个实例对象
private val staticTest = new StaticTest
println("老子说了算")
//提供一个公共的方法
def add(x:Int,y:Int) ={
staticTest.add(x,y)
}
}
object StaticTest2{
def main(args: Array[String]): Unit = {
println(StaticTest.add(2,3))
println(StaticTest.add(3,3))
println(StaticTest.add(4,3))
}
}
//”老子说了算“只打印一次
//老子说了算
//5
//6
//7
apply方法
当不是new关键字来创建对象的时候,使用apply可以是我们的代码更加简洁
class ApplyTest {
var name:String = _
var age:Int = _
}
object ApplyTest{
//方法中的参数不能使用val/val关键字
def apply(name:String): ApplyTest = {
val applyTest = new ApplyTest()
applyTest.name = name
applyTest
}
def apply(name:String,age:Int) : ApplyTest ={
val applyTest = new ApplyTest()
applyTest.name = name
applyTest.age = age
applyTest
}
def apply(applyTest: ApplyTest)={
val applyTest = new ApplyTest()
applyTest
}
}
object Test{
def main(args: Array[String]): Unit = {
//实例化调用
val applyTest = new ApplyTest()
applyTest.name = "苍老师"
applyTest.age = 18
println(s"name:${applyTest.name},age:${applyTest.age}")
//apply方法调用一个参数
val applyTest2 = ApplyTest("小泽老师")
println(s"name:${applyTest2.name},age:${applyTest2.age}")
//两个参数
val applyTest3 = ApplyTest("波多老师",20)
println(s"name:${applyTest3.name},age:${applyTest3.age}")
//对象
val applyTest4 = ApplyTest(applyTest)
println(s"name:${applyTest4.name},age:${applyTest4.age}")
}
}
继承
1.在scala中,让子类继承父类,与java一样,使用extends关键字
2.继承就代表,子类可以继承父类的field和method,然后子类可以在自己内部放入父类所没有,子类所特有的field和medthod
3.子类可以重写父类的field和method,但是需要注意的是final关键字,filnal关键字表示field和method不能重写
4.子类中的方法要重写父类的非抽象方法的话,需要override关键字
5.子类的属性val要重写父类的非抽象属性,必须要override
6.子类实现父类的抽象方法或者属性,可以选择性的使用override
abstract class Animal {
//抽象字段
var age:Int
//非抽象
val weight:Double = 35.0
//抽象方法
def color()
//非抽象
def eat(): Unit ={
println("吃肉")
}
//final关键字修饰,自身必须有具体的实现
//被final修饰不能被重写
final def action() = {
println("偷桃")
}
}
class Monkey extends Animal{
//重写父类抽象字段,可加可不加(override)
/*override*/ var age: Int = 3
//非抽象字段,必须加override
override val weight: Double = 40.0
//重写抽象方法,可加可不加
override def color(): Unit = {
println("棕色")
}
}
object Monkey{
def main(args: Array[String]): Unit = {
val monkey = new Monkey
monkey.color()
println(monkey.age)
println(monkey.weight)
}
}
特质trait
1.相当于java的接口,实际上比接口功能强大
2.与接口不同的是,特质可以定义属性和方法的实现
3.一般情况下scala的类只能被继承单一的父类,但是如果是特质的话可以实现多继承,从结果上来看实现了多继承
4.特质定义的方式与类类似,但是它使用的关键字是trait
trait TraitDemo01 {
//val修饰的非抽象字段,可以被重写
val name:String = "光头强"
//var修饰非抽象字段,不可以重写
var age:Int = 18
//抽象字段
var sex:String
//抽象方法
def say(context:String)
}
trait TraitDemo02{
def sayHello(context:String)
}
//多重实现
class TraitDemo extends TraitDemo01 with TraitDemo02{
//抽象 可加可不加
var sex: String = "男"
//非抽象字段必须加override
override val name: String = "熊大"
override def say(context: String): Unit = {
println(context)
}
override def sayHello(context: String): Unit = {
println(context)
}
}
object TraitDemo{
def main(args: Array[String]): Unit = {
val traitDemo = new TraitDemo
traitDemo.say("啊啊啊")
traitDemo.sayHello("hello!!")
println(traitDemo.name)
}
}
比较复杂的trait,加深理解
trait TraitDemo03 {
println("1:02的主代码块")
}
trait TraitDemo03_01 extends TraitDemo03{
println("2:03_01的主构造代码块")
}
trait TraitDemo03_02 extends TraitDemo03{
println("3:03_02的主构造代码块")
}
class Person{
println("4:Person的主代码块")
}
class Person01 extends Person with TraitDemo03 with TraitDemo03_01 with TraitDemo03_02 {
println("5:Person01的主代码块")
}
object Student{
def main(args: Array[String]): Unit = {
new Person01
}
}
/*
4:Person的主代码块
1:02的主代码块
2:03_01的主构造代码块
3:03_02的主构造代码块
5:Person01的主代码块
*/
trait小技巧
trait TraitDemo01_03{
def say={
println("hello world!")
}
}
class Boy(val name:String, var age:Int)
object Boy {
def main(args: Array[String]): Unit = {
val b1 = new Boy("熊大", 8)
//动态混入,混入之后的类型不在是普通的类型,而是实现了特质的类型
val b2 = new Boy("熊二", age = 7) with TraitDemo01_03
b2.say
}
}