Scala面向对象和模式匹配
我们要封装数据,定义模板等操作,所以我们需要面向对象。
一、scala中的单例对象
在scala当中,是没有static的,scala给我们提供了单例模式的实现方法。就是使用关键字object。
static在java中修饰属性和方法,目的是直接类名.进行调用。
在scala中object是一个单例对象
在scala中object定义的成员变量和方法都是静态的
可以通过 类名. 来进行调用
1、ScalaTest
object ScalaTest { //定义成员变量 val name: String = "tom" //定义方法public static def sleep(str: String): Unit = { println(str) } }
2、ScalaMain
/** * 在scala中object是一个单例对象 * 在scala中object定义的成员变量和方法都是静态的 * 可以通过 类名. 来进行调用 */ object ScalaMain { def main(args: Array[String]): Unit = { println(ScalaTest.name) ScalaTest.sleep("Tom睡得很香!") } }
结果:
二、scala类与构造器的使用
scala中主构造器:
定义在类名后面的构造器叫主构造器
scala辅助构造器:
定义在class类中,可以有多个辅助构造器
如果主构造器中成员变量属性没有被val var修饰的话,该属性不能被访问
相当于java中没有对外提供get方法
如果成员属性使用var修饰的话,相当于java中对外提供了get方法和set方法
如果成员属性使用val修饰的话,相当于java中对外只提供了get方法
1、Person1
//定义类 class Person1 { //定义姓名 年龄 var name: String = _ var age: Int = _ } //继承App特质 可以不写main object Test extends App{ val p = new Person1 p.name = "tom" p.age = 18 println(p.name) }
2、Person2
//定义主构造器 class Person2(name:String,age:Int) { } object Test2 extends App{ val p = new Person2("john",19) println(p) }
结果:
3、Person3
class Person3(var name:String,age:Int) { var high:Int = _ var weight:Int = _ //定义辅助构造器 def this(name:String,age:Int,high:Int){ //注意:在辅助构造器中必须先调用主构造器 this(name,age) this.high = high } //辅助构造器可以是多个 def this(name:String,age:Int,high:Int,weight:Int){ /* 如果主构造器中成员变量属性没有被val var修饰的话,该属性不能被访问 相当于java中没有对外提供get方法 如果成员属性使用var修饰的话,相当于java中对外提供了get方法和set方法 如果成员属性使用val修饰的话,相当于java中对外只提供了get方法 */ this(name,age) this.weight = weight } } object Test3 extends App{ val p1 = new Person3("tom",18) println(p1.name) }
结果:
三、构造器的访问权限
在主构造器或者辅助构造器前加上private修饰符即可
1、Person4
/* 类的构造器访问权限: private 私有 */ //主构造器设置为私有 class Person4 private (var name:String,age:Int) { var high: Int = _ private def this(name:String,age:Int,high:Int){ this(name,age) this.high = high } }
2、ScalaDemo
object ScalaDemo { def main(args: Array[String]): Unit = { //被private 修饰的主构造器 对外访问权限 val p = new Person4("hh",88) val p2 = new Person4("ff",33,190) println(p.name) println(p2.name) } }
结果:
四、类的访问权限
1、Person5
/** * 类的前面如果加上包名,表示当前类在当前包及其子包可见,可以访问 * [this}默认是它,表示当前包都有访问权限 */ private[this] class Person5(var name:String,age:Int) { var high:Int = _ def this(name:String,age:Int,high:Int){ this(name,age) this.high = high } }
2、Test
object Test { def main(args: Array[String]): Unit = { val p = new Person5("dd",18,188) println(p.name) } }
五、伴生对象
1、Person6
class Person6(private var name:String,age:Int) { var high:Int = _ def this(name:String,age:Int,high:Int){ this(name,age) this.high = high } } //注意:在伴生对象中可以访问类的私有成员方法和属性 //什么是伴生对象? 单例类名和类名相同 object Person6 extends App{ val p = new Person6("tom",18,180) println(p.name) }
六、特质
相当于java中Interface接口。
1、Animal
trait Animal { //定义未实现的方法 def eat(name:String) //定义实现的方法 def sleep(name:String): Unit = { println(s"$name -> 在睡觉") } }
2、Pig
object Pig extends Animal { override def eat(name: String): Unit = { println(s"$name -> 在吃饭") } override def sleep(name: String): Unit = { println(s"$name -> 做梦吃鸡") } def main(args: Array[String]): Unit = { Pig.eat("john") Pig.sleep("tom") } }
结果:
七、混入特质
1、Animal
trait Animal { //定义未实现的方法 def eat(name:String) //定义实现的方法 def sleep(name:String): Unit = { println(s"$name -> 在睡觉") } }
2、Running
trait Running { def how(str:String): Unit = { println(s"$str -> 在奔跑") } }
3、Dog
//混入特质 object Dog extends Animal with Running { override def eat(name: String): Unit = { println(s"$name -> 吃骨头") } override def sleep(name: String): Unit = { println(s"$name -> 长膘") } def main(args: Array[String]): Unit = { Dog.eat("小狗") Dog.how("金毛") } }
结果:
八、抽象类
1、AbstractDemo
//定义抽象类 abstract class AbstractDemo { def eat(food:String) def sleep(how:String): Unit = { println(s"$how -> 睡得很香") } }
2、AbstractImpl
//继承抽象类可以再继承特质 但是抽象类写在前 用with连接 object AbstractImpl extends AbstractDemo with Running { override def eat(food: String): Unit = { //ctrl + i println(s"$food -> 吃火锅") } def main(args: Array[String]): Unit = { AbstractImpl.eat("tom") AbstractImpl.how("john") } }
结果:
九、模式匹配
1、MatchTest
//模式匹配 object MatchTest { def main(args: Array[String]): Unit = { def strMatch(str:String) = str match { case "john" => println("很帅") case "mary" => println("很美") case _ => println("你是谁?") } strMatch("john") def arrayMatch(arr:Any) = arr match { case Array(1) => println("只有一个元素的数组") case Array(1,2) => println("有两个元素的数组") } arrayMatch(Array(1,2)) def tuple(tuple:Any) = tuple match { case (1,_) => println("元组的第一个元素为1,第二个元素任意") case ("tom",18) => println("这是个帅小伙") } tuple("tom",18) } }
结果:
十、final关键字
如果方法不想被重写可以使用final关键字进行修饰
用final修饰的:
类:类不能被继承
方法:不能被重写
val
1、Animal
trait Animal { //定义姓名 final var name:String = "tom" var age:Int = 18 def eat(name: String) final def sleep(name: String): Unit = { println(s"$name -> 睡得天花乱坠") } }
2、Pig
object Pig extends Animal { //重写eat方法 override def eat(name: String): Unit = { println(s"$name -> 吃吃吃") } //这里编译报错,final修饰方法不能被重写 override def sleep(name: String): Unit = { println(s"$name -> 做梦吃鸡") } def main(args: Array[String]): Unit = { Pig.eat("猪") Pig.sleep("john") Pig.name = "john tom" println(Pig.name) } }
十一、type关键字
别名设置
使我们的程序变得更灵活
T
1、Anl
trait Anl { //定义特质时可以不指定类型 type T def sleep(str: T): Unit = { println(str) } }
2、AnlTest
object AnlTest extends Anl { override type T = String def main(args: Array[String]): Unit = { AnlTest.sleep("睡得很香") } }
结果:
十二、样例类和样例对象
1)样例类 样例类支持模式匹配 写法:case class 类名(属性...) 2)样例对象 写法:case object 类名(属性...) 不能封装数据 支持模式匹配 case object Check match{ case "Check" => println(Check) }
1、TestEat
//样例类支持模式匹配 case class Eat(food:String,drink:String) object TestEat { def main(args: Array[String]): Unit = { val eat = new Eat("麻辣香锅","北冰洋") println(eat) } }
2、TestEat1
//样例类支持模式匹配 case class Boy(high:Int,weight:Int) case class Girl(high:Int,weight:Int) object TestEat1 extends App { def objMatch(obj:Any) = obj match { case Boy(x,y) => println(s"$x $y 的男孩") case Girl(x,y) => println(s"$x $y 的女孩") } objMatch(Boy(180,120)) objMatch(Girl(160,90)) }
结果: