Scala 学习 (六) 面向对象
2.1 类定义,主构造器,赋值构造器
2.2 访问权限
2.3 伴生类,apply方法
5.1 final关键字
5.2 type关键字
7.1 匹配字符串,类型,守卫
7.2 匹配数组
7.3 匹配集合
7.4 匹配元组
7.5 匹配样例类,样例对象
正文
一,scala单例对象
在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object, object 对象不能带参数。
如下实例:
/** * 单例对象 */ object ScalaSingleton { def saySomething(msg: String) = {
println(msg) } } object test { def main(args: Array[String]): Unit = {
ScalaSingleton.saySomething("滚犊子....")
println(ScalaSingleton)
println(ScalaSingleton) // 输出结果: // 滚犊子.... // cn.demo.ScalaSingleton$@28f67ac7 // cn.demo.ScalaSingleton$@28f67ac7 } }
二,scala类
2.1 类定义,主构造器,赋值构造器
定义类,和一些注意事项:
/* * 在 Scala 中,类并不用声明为 public。 * 如果你没有定义构造器, 类会有一个默认的空参构造器 * var 修饰的变量, 这个变量对外提供 getter setter 方法 * val 修饰的变量, 对外提供了 getter 方法,没有 setter **/ class Student { // _ 表示一个占位符, 编译器会根据你变量的具体类型赋予相应初始值 // 注意: 使用_ 占位符是, 变量类型必须指定 var name: String=_ var age: Int=_ // 错误代码, val 修饰的变量不能使用占位符 // val age: Int = _ 因为val修饰的不变的变量 val school: String = "beida" } object Test{ var name="zhangsan" def main(args: Array[String]): Unit = { // 调用空参构造器,可以加() 也可以不 var stu = new Student() // 类中使用 val 修饰的变量不能更改 // student.school = "nanda" stu.name = "laowang" println(s"student.name is ${stu.name}") // student.name is laowang println(s"test.name is ${Test.name}") // test.name is zhangsan } }
定义在类后面的为类主构造器, 一个类可以有多个辅助构造器
/* * Student1(val name: String, var age: Int) * 定义个 2 个参数的主构造器 **/ class Student1 (val name: String, var age: Int) { var gender: String = _ // 辅助构造器, 使用 def this // 在辅助构造器中必须先调用类的主构造器 def this(name: String, age:Int, gender: String){ this(name, age) this.gender = gender } } object Test1{ def main(args: Array[String]): Unit = { // 调用主构造器 val s = new Student1("laoduan", 38) println(s"${s.name} ${s.age}") // 调用的是辅助构造器 val s1 = new Student1("laoYang", 18, "male") println(s"${s1.gender}") } }
2.2 访问权限
构造器访问权限
/* * Student1(val name: String, var age: Int) * 定义个 2 个参数的主构造器 * private 加在主构造器前面标识这个主构造器是私有的, 外部不能访问这个构造器 * 这里的外部是值只有在本类才可以调用,即本类的辅助构造器才能调用。还有伴生类也可以访问 **/ class Student1 private (val name: String, var age: Int) { var gender: String = _ // 辅助构造器, 使用 def this // 在辅助构造器中必须先调用类的主构造器 def this(name: String, age:Int, gender: String){ this(name, age) // 这里调用了主构造器 this.gender = gender } } object Test1{ def main(args: Array[String]): Unit = { // 调用主构造器,若主构造器加上private,这里调用会报错 val s = new Student1("laoduan", 38) println(s"${s.name} ${s.age}") // 调用的是辅助构造器 val s1 = new Student1("laoYang", 18, "male") println(s"${s1.gender}") } }
成员变量访问权限
/* * private 加在主构造器前面标识这个主构造器是私有的, 外部不能访问这个构造器 * private var age * age 在这个类中是有 getter setter 方法的 * 但是前面如果加上了 private 修饰, 也就意味着, age 只能在这个类的内部以及其伴生类对象中可以访问修改 * 其他外部类不能访问 **/ class Student2 private (val name: String, private var age: Int){ var gender: String = _ def this(name: String, age: Int, gender: String){ this(name, age) this.gender = gender } // private[this]关键字标识该属性只能在类的内部访问, 伴生类不能访 private [this] val province: String = "北京" def getAge = 18 } // // 类的伴生对象 object Student2{ def main(args: Array[String]): Unit = { //伴生对象可以访问类的私有方法和属性 var s2 = new Student2("老王", 18) s2.age = 19 println(s"${s2.age}") // println(s"${s2.province}") 伴生类不能访问 } }
类包的访问权限
/* * private[包名] class 放在类声明最前面, 是修饰类的访问权限, 也就是说类在某些包下不可见或不能访问 * private[sheep] class 代表 student3 在 sheep 包下及其子包下可以见, 同级包中不能访问 * * */ private [this] class Student3(val name: String, private var age: Int){ var xx: Int = _ } object Student3{ def main(args: Array[String]): Unit = { var s3 = new Student3("wallace", 16) println(s"${s3.name}") } }
2.3 伴生类,apply方法
在 Scala 中, 当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象。必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类。类和它的伴生对象可以互相访问其私有成员。
三,特质
Scala Trait(特质) 相当于 Java 的接口,实际上它比接口还功能强大。与接口不同的是,它还可以定义属性和方法的实现。一般情况下 Scala 的类只能够继承单一父类,但是如果是 Trait(特质) 的话就可以继承多个,实现了多重继承。使用的关键字是trait .
trait TDemo2 { // 特质属性 var className: String = "牛B班" // 特质无实现方法 def teacherSay(name: String) // 特质有实现方法 def doSomeThing()={ print("aaaa") } }
四,抽象类
在scala中,使用abstract修饰的类为抽象类,在抽象类中可以定义属性,未实现的方法和已实现的方法。
如下实例:
abstract class AbsDemo1 { // 抽象类属性 var className: String = "牛B班" // 抽象类未实现方法 def teacherSay(name: String) // 抽象类已实现方法 def doSomeThing()={ print("aaaa") } }
五,继承
继承是面向对象的概念,用于代码的可重用性,被扩展的类称为超类或父类,扩展的类称为派生类或子类。Scala可以通过使用extends关键字来实现继承获其他类获特质。
父类:
abstract class Animal { // 定义一个name属性 val name: String = "animal" // 没有任何实现的方法 def sleep() // 带有实现的方法 def eat(f: String)={ println("$f") } }
子类:
class Dog extends Animal { /* * with 后面只能是特质 * 父类已经实现了的功能, 子类必须使用 override 关键字重写 * 父类没有实现的方法,子类必须实现 * */ override val name: String = "Dog" override def sleep(): Unit = { println("躺着睡。。。。") } }
5.1 final关键字
被 final 修饰的类不能被继承;
被 final 修饰的属性不能重写;
被 final 修饰的方法不能被重写
5.2 type关键字
Scala 里的类型,除了在定义 class,trait,object 时会产生类型,还可以通过 type 关键字来声明类型。
type 相当于声明一个类型别名:
父类:
trait StudentTrait { type T def learn(s: T) = { println(s) } }
子类:
object Student1 extends StudentTrait{ override type T = String def main(args: Array[String]): Unit = { Student1.learn("String") } } object Student2 extends StudentTrait { override type T = Int def main(args: Array[String]): Unit = { Student2.learn(100) } }
六,样例类,样例对象
/* * 样例类,使用 case 关键字 修饰的类, 其重要的特征就是支持模式匹配 * 样例类默认是实现了序列化接口的 * */ case class Message(msgContent: String) /* * 样例 object, 不能封装数据, 其重要特征就是支持模式匹配 **/ case object CheckHeartBeat object TestCaseClass extends App{ // 可以使用 new 关键字创建实例, 也可以不使用 val msg = Message( "hello") println (msg .msgContent) }
七,匹配模式
7.1 匹配字符串,类型,守卫
val arr = Array ( "YoshizawaAkiho", "YuiHatano", "AoiSola") val i = Random.nextInt( arr .length) println ( i ) val name = arr ( i ) println ( name ) name h match { case " "YoshizawaAkiho" => println (" " 吉泽老师 ...") case " "YuiHatano" => { println (" " 波多老师 ...") } case _ => println (" " 真不知道你们在说什么 ...") } println ( "----------- 骚气的分割线 -----------") //定义一个数组 val arr :Array[Any] = Array ( "hello123", 1, 2.0, CaseDemo02, 2L) //取出一个元素 val elem = arr (3) elem h match { case x: Int => println (t "Int " " + x) case y: Double if(y >= 0) => println ("Double " "+ y) // if 守卫 case z: String => println (g "String " " + z) case w: Long => println (g "long " " + w) case CaseDemo02 => { println ("case o demo 2") //throw new Exception("not match exception") } case _ => { // 其他任意情况 println ( "no") println ( "default") } }
7.2 匹配数组
val arr = Array (1, 1, 7, 0, 2,3) arr h match { case Array (0, 2, x, y) => println (x + " " " " + y) case Array (2, 1, 7, y) => println (y "only 0 0 " " + y) case Array (1, 1, 7, _*) => println (0 "0 ...") // _* 任意多个 case _ => println (g "something else") }
7.3 匹配集合
val lst = List(0, 3, 4) println(lst.head) println(lst.tail) lst match { case 0 :: Nil => println ("only 0") case x :: y :: Nil => println (s"x $x y $y" ") case 0 :: a => println (s"value: $a") case _ => println ("something else") }
7.4 匹配元组
val tup = (1, 3, 7) tup match { case (3, x, y) => println (s"hello 123 $x,$y") case (z, x, y) => println (s"$z,$x,$y") case (_, w, 5) => println (w) case _ => println("else") }
7.5 匹配样例类,样例对象
//样例类,模式匹配,封装数据(多例),不用 new 即可创建实例 case class SubmitTask(id: String, name: String) case class HeartBeat(time: Long) //样例对象,模式匹配(单例) case object CheckTimeOutTask val arr = Array (CheckTimeOutTask, new HeartBeat(123), HeartBeat (88888), new HeartBeat(666), SubmitTask ("0001","task-0001")) val i = Random.nextInt( arr .length) val element = arr ( i ) println( element ) element match { case SubmitTask (id, name) => { println (s"$id,$name") } case HeartBeat (time) => { println (time) } case CheckTimeOutTask => { println ("check") } }