一、类和对象
- 类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。
- 类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
- Scala中的类不声明为public,一个Scala源文件中可以有多个类。
- Scala 的类定义可以有参数,称为类参数,类参数在整个类中都可以访问。
scala面向对象基本上与Java SE中OOP(面向对象编程)类似。
- 在Scala中声明private变量,Scala编译器会自动生成get,set方法
- 在Scala中变量需要初始化
- 在Scala中没有静态修饰符static,在object下的成员全部都是静态的
- 如果在类中声明了与该类同名的object则该object是该类的”伴生对象”
- 可以理解为Scala把类中的static集中放到了object对象中,伴生对象和类文件必须是同一个源文件,可以用伴生对象做一些初始化操作.
- 在Java中可以通过interface实现多继承,在Scala中可以通过特征(trait)实现多重继承,但是与Java不同的是,它可以定义自己的属性和实现方法体
- object不能提供构造器参数,也就是说object必须是无参的
Scala中object与class的区别
在Scala中,类可以和对象同名,该对象称为该类的伴生对象,类和伴生对象可以相互访问他们的私有属性,但是它们必须在同一个源文件中
类只会被编译,不能直接执行,类的声明和主构造器在一起被声明,在一个类中,主构造器只有一个.
类和它的伴生对象可以相互访问其私有成员
class和object的一个差别是,单例对象不带参数,而类可以.因为你不能用new关键字实例化一个单例对象,你没有机会传递给它参数
1、类&属性&方法的定义
eg:
class People {
//定义属性
var name:String=""
val age:Int=10
//定义方法
def eat():String={
name+"eat pipea"
}
def watchFootball(teamName:String): Unit ={
println(name+"is watching match of "+teamName)
}
}
object SimpleObjectDemo {
def main(args: Array[String]): Unit = {
val people = new People() //创建对象
people.name="Messi" //为namme赋值
println("name is :"+people.name)
println("name is :"+people.name+"age is :"+people.age)
//函数调用
println("invoke eat method:"+people.eat())
//
println("incoke watchFootball method:"+people.watchFootball("Barcelona"))
}
}
2、构造方法
eg:
class ConstrutorExtendsDemo {
}
定义类时定义的方法参数是默认构造方法
class Person (val name:String,val age:Int){
println("Person constructor enter~~~~~~~~~~~~~~~~")
val school="kgc"
println("Person constructor leave~~~~~~~~~~~~~~~")
}
class ConstrutorExtendsDemo extends App{
//调用主构造器
var person=new Person("zhangsan",21)
println("name is:"+person.name+",age is :"+ person.age+",school is :"+person.school)
}
3、继承
Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:
- 重写一个非抽象方法必须使用override修饰符。
- 只有主构造函数才可以往基类的构造函数里写参数。
- 在子类中重写超类的抽象方法时,不需要使用override关键字。
class Student(name:String,age:Int,var major:String) extends Person(name,age){
println("Student constructor enter~~~~~~~~~")
println("Student constructor leave~~~~~~~~~~~~~~~")
}
class ConstrutorExtendsDemo extends App{
//初始化子类对象
var student = new Student("wangwu",15,"Math")
println("name is :"+ student.name + "age is :"+ student.age + "major is :"+ student.major + "school is :"+ student.school)
println(student)
}
注意:
- Scala 使用 extends 关键字来继承一个类。父类(基类),子类。
- 继承会继承父类的所有属性和方法,Scala 只允许继承一个父类。
- 子类构造方法触发之前要先触发其父类的构造方法
- 父类中已有的字段无需使用val/var修饰,只有新增的字段才需要val/var修饰
4、抽象类
scala中抽象类的特点:
1) 类的一个或多个方法没有完整的实现(只有定义,没有实现)
2)声明抽象方法不需要加abstract关键字,只需不写方法体
3)子类重写父类的抽象方法时不需加override
4)子类重写父类的抽象属性时不需加override
5)父类可以声明抽象字段(没有初始值的字段)
class AbstractDemo {
}
abstract class Person2 {
//属性和方法无需添加abstract关键字
def speak
val name:String
var age:Int
}
class Student2 extends Person2{
def speak(): Unit ={
//返回值为Unit
println("speak~~~~~~~~~~")
}
val name="zhangsan"
var age=100
}
class AbstractDemo extends App{
val s = new Student2
s.speak()
println("name is:"+s.name+",age is "+s.age)
}
5、单例对象
在 Scala 中没有 static 关键字,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。
- scala 的object 中所有成员变量和方法默认都是 static 的,所以可以直接访问main方法
Scala 中使用单例模式时,除了定义的类之外,还要定义一个与类同名的 object 对象,区别是:object对象不能带参数。
- 当单例对象与类同名时,该单例对象被称作是该类的伴生对象:companion object。
- 类和其伴生对象必须在同一个源文件里,该类被称为是这个单例对象的伴生类:companion class。
- 类和其伴生对象可以互相访问其私有成员。
eg:单例对象实例
class Point(val xc: Int, val yc: Int) { var x: Int = xc var y: Int = yc def move(dx: Int, dy: Int) { x = x + dx y = y + dy } } object Test { def main(args: Array[String]) { val point = new Point(10, 20) printPoint def printPoint{ println ("x 的坐标点 : " + point.x); println ("y 的坐标点 : " + point.y); } } }
eg:伴生对象实例:
//私有构造方法 class Marker private(val color:String){ println("创建"+this) override def toString(): String = "颜色标记"+color } //伴生对象,与类共享名,可以访问类的私有属性和方法 object Marker { //定义了一个map类型的变量--》markers private val markers:Map[String,Marker] = Map( "red" -> new Marker("red"), "blue" -> new Marker("blue"), "green" -> new Marker("green") ) def apply(color: String)={ if (markers.contains(color)) markers(color) else null } def getMarker(color: String)={ if (markers.contains(color)) markers(color) else null } def main(args: Array[String]){ println(Marker("red")) //单例函数调用 println(Marker.getMarker("blue")) } }
二、特征 Trait
scala Trait(特征)相当于java中的接口,实际比接口功能强大。
区别于接口:scala Trait还可以定义属性和方法的实现。
一般情况下,scala类只能继承单一父类,但是scala Trait(特征)可实现多重继承
使用关键字trait定义特征
子类继承特征可以实现未被实现的方法。所以其实 Scala Trait(特征)更像 Java 的抽象类。
eg:
//isEqual方法没有定义方法的实现,isNotEqual定义了方法的实现
trait Equal {
def isEqual(x: Any): Boolean
def isNotEqual(x: Any): Boolean = !isEqual(x)
}
子类继承特征可以实现未被实现的方法class Point(xc:Int,yc:Int) extends Equal{
var x:Int = xc
var y:Int = yc
def isEqual(obj:Any)=
//类型判断
obj.isInstanceOf[Point]&&
//强制类型转换
obj.asInstanceOf[Point].x == x
}
object Test {
def main(args: Array[String]) {
val p1 = new Point(2,3)
val p2 = new Point(2,4)
val p3 = new Point(3,3)
println(p1.isNotEqual(p2)) //true
println(p1.isNotEqual(p3)) //true
println(p1.isNotEqual(2)) //true
}
}
特征构造顺序
特征也可以有构造器,由字段的初始化和其他特征体中的语句构成。这些语句在任何混入该特征的对象在构造时都会被执行。
构造器的执行顺序:
- 调用超类的构造器;
- 特征构造器在超类构造器之后、类构造器之前执行;
- 特征由左到右被构造;
- 每个特征当中,父特征先被构造;
- 如果多个特征共有一个父特征,父特征不会被重复构造
- 所有特征被构造完毕,子类被构造。
构造器的顺序是类的线性化的反向。线性化是描述某个类型的所有超类型的一种技术规格。
三、模式匹配
Scala 提供了强大的模式匹配机制,应用也非常广泛。
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。
箭头符号 => 隔开了模式和表达式。
eg:
match 对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。
match 表达式通过以代码编写的先后次序尝试每个模式来完成计算,只要发现有一个匹配的case,剩下的case不会继续匹配。
eg:不同数据类型的模式匹配
实例中第一个 case 对应整型数值 1,第二个 case 对应字符串值 two,第三个 case 对应类型模式,用于判断传入的值是否为整型,相比使用isInstanceOf来判断类型,使用模式匹配更好。第四个 case 表示默认的全匹配备选项,即没有找到其他匹配时的匹配项,类似 switch 中的 default。
1、样例类case class
使用了case关键字定义的类---->样例类(case classes),样例类是特殊的类,经过优化以用于模式匹配。
eg:
在声明样例类时,下面的过程自动发生了:
- 构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
- 在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
- 提供unapply方法使模式匹配可以工作;
- 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。