Scala-Unit5-Scala面对对象与模式匹配
Posted hellobigtable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala-Unit5-Scala面对对象与模式匹配相关的知识,希望对你有一定的参考价值。
Java中的面向对象:万物皆对象。
我们要封装数据,定义模板等操作,素以我们需要面向对象。
=========================================================================
一、Scala中的单例对象
在java中用static关键字修饰方法或成员变量,作用是可以直接通过"类名."的方式调用方法或变量
在Scala中没有static关键字,Scala给我们提供了单例对象的模式来实现,关键字是object
object Person { //定义成员变量 val name:String = "Hunter" //定义类方法 def sleep(str:String):Unit= { println(str) } } object ScalaDemo{ def main(args: Array[String]): Unit = { print(Person.name) Person.sleep("睡得很香") } }
在Scala中的object是一个单例对象,object中定义的方法和成员变量都是静态的,在其他的单例对象中可以直接通过“类名.”的方式进行调用。
main方法也只能定义在object中,因为java中main方法为静态方法。
通过class创建的类中定义的方法和对象不能直接调用,不许构造函数对象后才可调用。
二、Scala类与构造器的使用
1.类的定义和使用,例子:
class Person1 { //定义成员变量姓名、年龄 var name:String = _ var age:Int = _ //注释:_的意思是不给定,可以在其他类或单例对象中调用赋值,所以用var定义 } //继承App特质,可以不写main方法,类似java的Test/Before object Test1 extends App{ val p = new Person1 p.name = "reba" p.age = 18 println(p.name + p.age + "岁") }
2.主构造器:写在类名后面的构造器是主构造器
class Person2 (name:String,age:Int){ } object Test2 extends App{ val p = new Person2("yangmi",24) println(p) println(p.toString) //这两行输出的都是地址,原因见辅助构造器 }
注意:主构造器里的变量没有var,val修饰不能被调用
3.辅助构造器:定义在类内部的构造器,一个类中可以有多个辅助构造器
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){ this(name,age) this.high = high this.weight = weight } } object Test3 extends App{ val p = new Person3("Hunter",34,180,140) p.weight = 150 println(p.name + "身高:" +p.high + ",体重:" + p.weight) }
注意:(1)辅助构造器内必须先声明主构造器中的所有变量,在声明自己的变量
(2)Scala中主构造器中的变量如果没有被val、var修饰的话,是不能被访问的,
相当于java没有给这个变量get/set方法;
如果主构造器中的变量被val修饰,相当于提供了java中的get方法,
如果主构造器中的变量被var修饰,相当于提供了java中的get和set方法。
4.构造器的访问权限:private
在主构造器或辅助构造器前添加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 } } object ScalaDemo{ def mian(args:Array[String]):Unit ={ val p = new Person4("h",88) val p1 = new Person3(name = "r",age =18) println(p.name) } }
注意:编译时Idea不报错,运行时才会报错;
但是编程时如果主构造器不是私有的,定义时会出现变量名的提示(如Person3,而Person4没有提示)
5.类的访问权限,在类前添加private修饰
测试:
//测试封装类如下,[this]会根据情况变化为无、[scala04]父包、[demo]子包
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 } }
//测试运行单例对象如下:
object ScalaDemo { def main(args: Array[String]): Unit = { val p = new Person5("h",18,182) println(p.name) } }
1>>封装类在父包,省略this,测试类在父包 √
2>>封装类在父包,省略this,测试类在子包 √
3>>封装类在父包,添加this,测试类在子包 √
4>>封装类在父包,添加this,测试类在父包 √
5>>封装类在父包,添加demo,测试类在父包 ×
6>>封装类在父包,添加demo,测试类在子包 ×
7>>封装类在父包,添加scala04,测试类在子包 √
8>>封装类在父包,添加scala04,测试类在父包 √
1>>封装类在子包,省略this,测试类在子包 √
2>>封装类在子包,省略this,测试类在父包 ×
3>>封装类在子包,添加this,测试类在父包 ×
4>>封装类在子包,添加this,测试类在子包 √
5>>封装类在子包,添加Scala04,测试类在子包 √
6>>封装类在子包,添加Scala04,测试类在父包 √
7>>封装类在子包,添加demo,测试类在父包 ×
8>>封装类在子包,添加demo,测试类在子包 √
总结:(1)private[this]修饰类表示当前包下及其子包都可以访问,[this]可以省略;
(2)若在子包中定义private类,只能子包访问,如想父包访问,需要在private后添加[父包名]
(3)若在父包中定义private类,且添加[子包名],则父包与子包都无法访问该类
三、伴生对象:
定义:在同一个类文件中,单例对象名与类名相同的两个单例对象和类,称之为伴生对象。
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{ def main(args: Array[String]): Unit = { val p = new Person6("hunter",30) println(p.name) } }
注意:单例对象可以访问其伴生对象类的私有成员变量和方法,
但伴生对象他们必须在同一个类文件中。
四、Scala特质和混入特质
特质:相当于java中的接口
混入特质:相当与实现多个接口
trait Animal { //定义未实现方法 def eat(name:String) //定义实现的方法 def sleep(name:String):Unit={ println(s"$name 在睡觉") } } trait Running { def how(str:String) } object Pig extends Animal with Running { override def eat(name: String): Unit = { println(s"$name 在吃鸡") } override def how(str: String): Unit = { println(f"$str 在奔跑") } def main(args: Array[String]): Unit = { Pig.sleep("reba") Pig.eat("wyh") Pig.how("hunter") } }
注意:(1)Scala中没有implement,只有extends
(2)Idea中ctrl+i与ctrl+o的区别:
ctrl+i:实现未实现的方法
ctrl+o:重写已经实现的方法
五、Scala抽象类
abstract class AbstractDemo { def eat(food:String) def sleep(how:String):Unit={ println(s"$how->很香") } } object AbstractImpl extends AbstractDemo { override def eat(food: String): Unit = { println(s"hunter is eating $food") } override def sleep(how: String): Unit ={ println(s"hunter 睡得$how") } def main(args: Array[String]): Unit = { AbstractImpl.eat("大猪蹄子") AbstractImpl.sleep("很香") } }
注意:Scala中可以先继承抽象类在继承特质,但是抽象类必须写在前面!!
六、模式匹配(match/case)
以下为三个模式匹配的例子,分别匹配了字符串、数组、元祖三种类型:
object MatchTest { def main(args: Array[String]): Unit = { def strMatch(str:String):Unit = str match { case "Hunter" => println("很帅?") case "reba" => println("真的美") case _ => println("what?") } strMatch("Hunter") strMatch("hunter") def ArrayMatch(arr:Any):Unit = arr match { case Array(1) => println("只有一个元素的数组") case Array(1,2) => println("有两个元素的数组") } ArrayMatch(Array(1)) def tupleMatch(tuple:Any):Unit = tuple match { case (1,_) => println("元祖第一个元素为1,第二个元素为任意类型") case ("hunter",34) => println("这哥们老帅了") } tupleMatch(("hunter",34)) } }
以上是关于Scala-Unit5-Scala面对对象与模式匹配的主要内容,如果未能解决你的问题,请参考以下文章