寒假学习日报(三十九)——scala包的补充与新的知识学习
今天学习的东西有很多,主要是赶进度,写了不少样例代码方便理解。现在先记录一部分,若有补充会在该博客后续补上。
scala的包知识
昨天已经写了一些关于包的知识,但并不完整,今天上午将包这一板块学完了,现在重新进行梳理:
scala中父类与子类的操作和java相比还是有很多不同的,我个人认为跟scala的灵活性有关,java在创建时包名文件名什么的都要一致,而scala不需要,这给了充分自由的同时,也造成了访问时的指定问题,而且为了能够对类进行更细致的操作,scala还有“包对象”的概念
//scala支持在一个文件中创建多个包 package com.chapter01.packageabout { //包com.chapter01.packageabout class OutPack { //在com.chapter01.packageabout下创建类 var name = "Outpackage" def play(message: String): Unit = { println(this.name + " " + message) } } class User { //若父包想访问子包的类,需要声明 def sayHello: Unit = { //可以使用import引入 import com.chapter01.packageabout.newpackagetry.Monster val monster = new Monster //也可以通过路径声明 val monster2 = new com.chapter01.packageabout.newpackagetry.Monster2 } } //包对象 //每一个包都可以有一个包对象,注意对象名字要和包名一样 //在包对象中可以定义变量,方法,这些变量方法也可以在包中使用 package object newpackagetry{ val who = "what" def sayHi(): Unit ={ println("Hi!") } } package newpackagetry { //包com.chapter01.packageabout.newpackagetry class Pack { //在com.chapter01.packageabout.newpackagetry下创建类Pack var name = "package" def play(message: String): Unit = { println(this.name + " " + message) } } class User { } class Monster { } class Monster2 { } object packagetry { //在com.chapter01.packageabout.newpackagetry下创建object packagetry def main(args: Array[String]): Unit = { println("ok") //可以直接访问父包的类 val op = new OutPack println("op=" + op) //若子包和父包存在同名类,就近原则 val user = new User println("user=" + user) //若想访问同名父包类,声明路径 val user2 = new com.chapter01.packageabout.User() //使用包对象中的变量和方法 println("包对象中的who变量:" + who) print("包对象中的sayHi方法:") sayHi() } } } }
而和java相同,scala同样有public,protected,private这样的访问权限划分,而且在对protected的访问处理上,scala要更严苛一些,而且在设置访问权限的时候,也有了更多的方法。下面伴生类与伴生对象就是scala在去掉static之后诞生的。
package com.chapter01.packageabout object visitabout { def main(args: Array[String]): Unit = { val c = new Clerk() c.showInfo() Clerk.test(c) val v1 = new vper() //增加权限后可以访问指定权限的私有属性 println(v1.name) } } class Clerk { //默认是public权限,但注意scala中没有public关键字,且反编译时会发现实际上是private类型 var name: String = "Jack" private var sal: Double = 8099.9 //保护权限,同包无法使用,只能在子类中使用 protected var age = 10 def showInfo(): Unit = { println("name=" + name + " sal=" + sal) } } //当出现class Clerk和object Clerk时 //class Clerk为伴生类,object Clerk为伴生对象 //伴生类写非静态内容,伴生对象是静态内容 object Clerk{ def test(c: Clerk): Unit ={ //伴生对象中可以访问伴生类的私有属性 println("test()name=" + c.name + " sal=" + c.sal) } } class vper { //增加包访问权限 private[packageabout] val name = "vper" }
scala对包的引入有很多的手段
package com.chapter01.packageabout import scala.beans.BeanProperty class BeanAbout { //使用相对路径引入包 @BeanProperty var age: Int = _ //使用相对路径引入包2 @scala.beans.BeanProperty var age2: Int = _ //使用绝对路径引入包 @_root_.scala.beans.BeanProperty var age3: Int = _ } object inbean { def main(args: Array[String]): Unit = { } }
我们都知道scala是用于spark进行数据处理的,效率就是关键,为了提高效率,减少包的索引是一个考量因素,因此scala对引入包的处理有了更多的手段:
package com.chapter01.packageabout import scala.beans._ import scala.collection.mutable //表示将该包所有内容引入,等价于* object inputabout { def main(args: Array[String]): Unit = { } } class User { import scala.beans.BeanProperty //需要时引入,作用域在{}内 @BeanProperty var name: String = _ def test(): Unit = { //选择器引入包的指定内容 import scala.collection.mutable.{HashMap, HashSet} var map = new HashMap() var set = new HashSet() } def test2(): Unit = { //将java.util.HashMap重命名,这是临时生效的 import java.util.{HashMap => JavaHashMap, List} import scala.collection.mutable._ var map = new HashMap() var javamap = new JavaHashMap() } def test3(): Unit ={ //还可以将不用的类隐藏掉,仍然以HashMap为例 //第一个_指HashMap被隐藏,第二个_指引入java.util包下的其他内容 import java.util.{HashMap => _, _} import scala.collection.mutable._ //此时再声明HashMap不会使用java.util中的HashMap,idea中也不会给提示 var map = new HashMap() } }
以上是对scala包操作的一些总结。
下面说一些新的知识,这些知识我后续可能还会有一些补充,在半夜12点之前。若是过了12点,那新学的内容会在明日的日报中进行总结
继承:
package com.chapter01.extendsabout object Extends01 { def main(args: Array[String]): Unit = { val sub = new Sub() sub.sayOK() } } //父类(基类) class Base { var n1: Int = 1 //public n1(), public n1_$eq() protected var n2: Int = 2 private var n3: Int = 3 def test100(): Unit = { //默认public test100() println("base 100") } protected def test200(): Unit = { //反编译属于public类型,但只有子类可访问,同包不可访问 println("base 200") } private def test300(): Unit = { println("base 300") } } //Sub继承 class Sub extends Base { def sayOK(): Unit = { this.n1 = 20 //访问本质仍然是this.n1_$eq() this.n2 = 40 //n3无法访问,因为是私有类型 println("范围:" + this.n1 + this.n2) test100() test200() //test300()同样无法访问,因为也是私有类型 } }
重写:
package com.chapter01.extendsabout object methodoverride01 { def main(args: Array[String]): Unit = { val empo = new OEmp empo.printName() } } class OPerson { var name: String = "John" def printName(): Unit ={ println("OPerson printName()" + name) } } class OEmp extends OPerson { //重写的方法需要声明override override def printName(): Unit = { println("OEmp printName()" + name) //在子类中需要调用重写的父类方法时,使用super super.printName() } }
类与类之间的类型转换:
package com.chapter01.extendsabout object TypeConvert { def main(args: Array[String]): Unit = { //classOf:可以得到类名 println(classOf[String]) val s = "king" println(s.getClass.getName) //使用反射机制 //isInstanceOf asInstanceOf var o1 = new OPerson2 var e1 = new OEmp2 //将子类引用给父类(向上转型),这步是自动执行的,不需要声明isInstanceOf o1 = e1 println(o1.isInstanceOf[OEmp2]) //true //将父类引用重新转成子类引用(多态),向下转型 var e2 = o1.asInstanceOf[OEmp2] e2.sayHello() } } class OPerson2 { var name: String = "John" def printName(): Unit ={ println("OPerson printName()" + name) } def sayHi(): Unit ={ println("Hi") } } class OEmp2 extends OPerson2 { //重写的方法需要声明override override def printName(): Unit = { println("OEmp printName()" + name) //在子类中需要调用重写的父类方法时,使用super super.printName() } def sayHello(): Unit ={ println("Hello") } }