Scala入门到精通——第八节 包和引入
本節(jié)主要內(nèi)容
包的作用與定義
同Java中的包、C++中的命名空間一樣,Scala中的包主要用于大型工程代碼的組織同時(shí)也解決命名沖突的問題。scala中的包與java有著諸多的相似之處,但Scala語言中的包更加靈活。
//將代碼組織到cn.scala.xtwy包中 package cn.scala.xtwyabstract class Animal {//抽象字段(域)var height:Int//抽象方法def eat:Unit }class Person(var height:Int) extends Animal{override def eat()={println("eat by mouth")}}object Person extends App{new Person(10).eat() }- 1
上述包也可通過下面的包定義方式進(jìn)行:
//下面的代碼定義了一個(gè)cn.scala.xtwy包 //在程序的任何地方都可以通過cn.scala.xtwy.Teacher來使用Teacher這個(gè)類 package cn{package scala{package xtwy{class Teacher {}}} }- 1
將上面的代碼命名為Teacher.scala,代碼組織如下:
可以看到我們將代碼放在默認(rèn)包下面,但編碼后的字節(jié)碼文件被自動(dòng)組織到cn.scala.xtwy文件夾當(dāng)中,如下圖
可以看出,我們可以在任何地方進(jìn)行包中類的定義,scala幫助我們進(jìn)行自動(dòng)文件組織
我們將Teacher.scala內(nèi)容修改如下:
package cn{package scala{package xtwy{class Teacher {}}} } //添加了cn.scala.spark包,包中定義了一個(gè)SparkDemo類 package cn{package scala{package spark{class SparkDemo{}}} }- 1
下圖給出的是Teacher.scala編譯后產(chǎn)生的包文件:
通過前面的介紹,我們知道了如何定義包,包是怎么組織代碼的。在實(shí)際開發(fā)過程當(dāng)中,盡量使用java包的定義方式并將代碼集中進(jìn)行管理,這樣別人讀代碼的時(shí)候更方便,代碼更簡(jiǎn)潔。
包的作用域與引入(import)的使用方法
下面的代碼給出了包的作用域和引入的使用方法
package cn{package scala{//在包c(diǎn)n.scala下創(chuàng)建了一個(gè)Utils單例object Utils{def toString(x:String){println(x)}//外層包無法直接訪問內(nèi)層包,下面這一行代碼編譯通不過//def getTeacher():Teacher=new Teacher("john")//如果一定要使用的話,可以引入包import cn.scala.xtwy._def getTeacher():Teacher=new Teacher("john")}//定義了cn.scala.xtwypackage xtwy{class Teacher(var name:String) {//演示包的訪問規(guī)則//內(nèi)層包可以訪問外層包中定義的類或?qū)ο?#xff0c;無需引入def printName()={Utils.toString(name)}}}} } object appDemo{//scala允許在任何地方進(jìn)行包的引入,_的意思是引入該包下的所有類和對(duì)象import cn.scala._import cn.scala.xtwy._def main(args: Array[String]): Unit = {Utils.toString(new Teacher("john").name)new Teacher("john").printName() }}訪問控制
在java語言中,主要通過public、private、protected及默認(rèn)控制來實(shí)現(xiàn)包中類成員的訪問控制,當(dāng)定義一個(gè)類時(shí),如果類成員不加任何訪問控制符時(shí),表示該類成員在定義該類的包中可見。在scala中沒有public關(guān)鍵字,僅有private 和 protected訪問控制符,當(dāng)一個(gè)類成員不加private和protected時(shí),它的訪問權(quán)限就是public。下面逐個(gè)進(jìn)行講解:
1 private 成員
private成員同java是一樣的,所有帶該關(guān)鍵字修飾的成員僅能在定義它的類或?qū)ο笾惺褂?#xff0c;在外部是不可見的
2 protected 成員
在java語言中,protected成員不但可以被該類及其子類訪問,也可以被同一個(gè)包中的其它類使用,但在scala中,protected成員只能被該類及其子類訪問
3 無修飾符成員
無修飾符的成員同java 的public,可以在任何位置進(jìn)行訪問
4 范圍保護(hù)
在scala中提供了更為靈活的訪問控制方法,private、protected除了可以直接修飾成員外,還可以以private[X]、protected[X]的方式進(jìn)行更為靈活的訪問控制,這種訪問控制的意思是可以將private、protected限定到X,X可以是包、類,還可以是單例對(duì)象
private[this],限定只有該類的對(duì)象才能訪問,稱這種成員為對(duì)象私有成員
package cn.scala.xtwy;class Teacher(var name: String) {private[this] def printName(tName:String="") :Unit= { println(tName) }//調(diào)用private[this] printName方法def print(n:String)=this.printName(n) }object Teacher{//private[this]限定的成員,即使伴生對(duì)象Teacher也不能使用//def printName=new Teacher("john").printName() }object appDemo {def main(args: Array[String]): Unit = {//編譯不能通過//new Teacher("john").printName()}}private,定義的類及伴生對(duì)象可以訪問
package cn.scala.xtwy;class Teacher(var name: String) {private def printName(tName:String="") :Unit= { println(tName) }//可以訪問def print(n:String)=this.printName(n) }object Teacher{//伴生對(duì)象可以訪問def printName=new Teacher("john").printName() }object appDemo {def main(args: Array[String]): Unit = {//不能訪問//new Teacher("john").printName()}}下面給出的是訪問規(guī)則表
| 無任何修飾符 | 任何地方都可以使用 |
| private[scala] | 在定義的類中可以訪問,在scala包及子包中可以訪問 |
| private[this] | 只能在定義的類中訪問,即使伴生對(duì)象也不能訪問團(tuán) |
| private | 在定義的的類及伴生對(duì)象中可以訪問,其它地方不能訪問 |
| protected[scala] | 在定義的類及子類中可以訪問,在scala包及子包中可以訪問, |
| protected[this] | 只能在定義的類及子類中訪問,即使伴生對(duì)象也不能訪問 |
| protected | 在定義的類及子類中訪問,伴生對(duì)象可以訪問,其它地方不能訪問 |
包對(duì)象
包對(duì)象主要用于將常量、工具函數(shù),使用時(shí)直接通過包名引用
//下面的代碼給出了包對(duì)象的定義 package cn.scala.xtwy//利用package關(guān)鍵字定義單例對(duì)象 package object Math {val PI=3.141529val THETA=2.0val SIGMA=1.9 }class Coputation{def computeArea(r:Double)=Math.PI*r*r }上述代碼編譯后會(huì)生成下列文件:
對(duì)應(yīng)字節(jié)碼文件如下:
D:\ScalaWorkspace\ScalaChapter08\bin\cn\scala\xtwy\Math>javap -private package.c lass Compiled from "Math.scala" public final class cn.scala.xtwy.Math.package {public static double SIGMA();public static double THETA();public static double PI(); }D:\ScalaWorkspace\ScalaChapter08\bin\cn\scala\xtwy\Math>javap -private package$. class Compiled from "Math.scala" public final class cn.scala.xtwy.Math.package$ {public static final cn.scala.xtwy.Math.package$ MODULE$;private final double PI;private final double THETA;private final double SIGMA;public static {};public double PI();public double THETA();public double SIGMA();private cn.scala.xtwy.Math.package$(); }不能看出,它為我們的包對(duì)象Math創(chuàng)建了一個(gè)文件夾,然后創(chuàng)建了兩個(gè)類,通過單例的方式實(shí)現(xiàn)方法調(diào)用。
import高級(jí)特性
1 隱式引入
在集合那一講,我們提到,如果不引入任何包,scala會(huì)默認(rèn)引入java.lang._
scala._
Predef._
包中或?qū)ο笾兴械念惡头椒?#xff0c;稱這種引入會(huì)隱式引入
2 重命名
scala中允許對(duì)引入的類或方法進(jìn)行重命名,如果我們需要在程序中同時(shí)使用java.util.HashMap及scala.collection.mutable.HashMap時(shí),可以利用重命名的方法消除命名沖突的問題,雖然也可以采用包名前綴的方式使用,但代碼不夠簡(jiǎn)潔
//將java.util.HashMap重命名為JavaHashMap import java.util.{ HashMap => JavaHashMap } import scala.collection.mutable.HashMap object RenameUsage {def main(args: Array[String]): Unit = {val javaHashMap = new JavaHashMap[String, String]()javaHashMap.put("Spark", "excellent")javaHashMap.put("MapReduce", "good")for(key <- javaHashMap.keySet().toArray){println(key+":"+javaHashMap.get(key))}val scalaHashMap=new HashMap[String,String]scalaHashMap.put("Spark", "excellent")scalaHashMap.put("MapReduce", "good")scalaHashMap.foreach(e=>{val (k,v)=eprintln(k+":"+v)})}}3 類隱藏
//通過HashMap=> _,這樣類便被隱藏起來了 import java.util.{HashMap=> _,_} import scala.collection.mutable.HashMapobject RenameUsage {def main(args: Array[String]): Unit = {//這樣的話,HashMap便無歧義地指向scala.collection.mutable.HashMapval scalaHashMap=new HashMap[String,String]scalaHashMap.put("Spark", "excellent")scalaHashMap.put("MapReduce", "good")scalaHashMap.foreach(e=>{val (k,v)=eprintln(k+":"+v)})}- 1
內(nèi)部類
前面我們提到過內(nèi)部類,我們看到內(nèi)部類可以像類的其它成員一樣訪問外部類的私有成員,本小節(jié)將對(duì)內(nèi)部類進(jìn)行更加詳細(xì)的介紹。
要點(diǎn)1:外部類不能訪問內(nèi)部類的成員域,但內(nèi)部類可以直接訪問外部類成員域,哪怕這個(gè)成員域是private私有的
class OuterClass {//即使定義為 private[this] var x:Int=0,也是可行的private var x:Int=0//def getInnerY=y,外部類不能直接訪問內(nèi)部類的成員域class InnerClass{private var y:Int=0//內(nèi)部的類可以直接訪問外部類的成員變量和成員方法,注意外部類的成員變量是privatedef getOuterX= x} }object AppDemo{def main(args: Array[String]): Unit = {val o=new OuterClass//創(chuàng)建內(nèi)部類對(duì)象,通過o.InnerClass方式,InnerClass就像是OuterClass的成員變量一樣val i=new o.InnerClassprintln(i.getOuterX)} }從上述代碼可以看出,內(nèi)部類除了是一個(gè)類之外,與外部類的成員沒有任何區(qū)別,它可以與外部類的成員域一樣被使用。
總結(jié)
以上是生活随笔為你收集整理的Scala入门到精通——第八节 包和引入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Scala入门到精通——第七节:类和对象
- 下一篇: ArcGis中空间连接join