本节主要内容

  1. 包的作用与定义
  2. 包的作用域与引入(import)的使用方法
  3. 访问控制
  4. 包对象
  5. import高级特性
  6. 内部类

包的作用与定义

同Java中的包、C++中的命名空间一样,Scala中的包主要用于大型工程代码的组织同时也解决命名冲突的问题。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

上述包也可通过下面的包定义方式进行:

//下面的代码定义了一个cn.scala.xtwy包
//在程序的任何地方都可以通过cn.scala.xtwy.Teacher来使用Teacher这个类
package cn{package scala{package xtwy{class Teacher {}}}
}
  • 1

将上面的代码命名为Teacher.scala,代码组织如下:

可以看到我们将代码放在默认包下面,但编码后的字节码文件被自动组织到cn.scala.xtwy文件夹当中,如下图

可以看出,我们可以在任何地方进行包中类的定义,scala帮助我们进行自动文件组织

我们将Teacher.scala内容修改如下:


package cn{package scala{package xtwy{class Teacher {}}}
}
//添加了cn.scala.spark包,包中定义了一个SparkDemo类
package cn{package scala{package spark{class SparkDemo{}}}
}
  • 1

下图给出的是Teacher.scala编译后产生的包文件:

通过前面的介绍,我们知道了如何定义包,包是怎么组织代码的。在实际开发过程当中,尽量使用java包的定义方式并将代码集中进行管理,这样别人读代码的时候更方便,代码更简洁。

包的作用域与引入(import)的使用方法

下面的代码给出了包的作用域和引入的使用方法

package cn{package scala{//在包cn.scala下创建了一个Utils单例object Utils{def toString(x:String){println(x)}//外层包无法直接访问内层包,下面这一行代码编译通不过//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) {//演示包的访问规则//内层包可以访问外层包中定义的类或对象,无需引入def printName()={Utils.toString(name)}}}}
}
object appDemo{//scala允许在任何地方进行包的引入,_的意思是引入该包下的所有类和对象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及默认控制来实现包中类成员的访问控制,当定义一个类时,如果类成员不加任何访问控制符时,表示该类成员在定义该类的包中可见。在scala中没有public关键字,仅有private 和 protected访问控制符,当一个类成员不加private和protected时,它的访问权限就是public。下面逐个进行讲解:

1 private 成员
private成员同java是一样的,所有带该关键字修饰的成员仅能在定义它的类或对象中使用,在外部是不可见的

class Student(var name:String,var age:Int){private var sex:Int=0//内部类class Course(val cName:String,val gpa:Float){//可以直接访问其外部类的私有成员def getStudentSex(student:Student)= student.sex}
}//班级类
class Class{//下面这条语句统计通不过,因为sex是私有的// def getStudentSex(student:Student)=student.sex
}
object Student {private var studentNo:Int=0;def uniqueStudentNo()={studentNo+=1studentNo}def apply(name:String,age:Int)=new Student(name,age)def main(args: Array[String]): Unit = {println(Student.uniqueStudentNo())val s=new Student("john",29)//直接访问伴生类Student中的私有成员println(s.sex)val s1=Student("john",29)println(s1.name)println(s1.age)//使用内部类val c1=new s1.Course("Scala",3.0f)}
}

2 protected 成员
在java语言中,protected成员不但可以被该类及其子类访问,也可以被同一个包中的其它类使用,但在scala中,protected成员只能被该类及其子类访问

class SuperClass {protected def f()=println(".....")
}class SubClass extends SuperClass{f()
}class OtherClass{//下面这个语句会报错//f()
}

3 无修饰符成员
无修饰符的成员同java 的public,可以在任何位置进行访问

4 范围保护
在scala中提供了更为灵活的访问控制方法,private、protected除了可以直接修饰成员外,还可以以private[X]、protected[X]的方式进行更为灵活的访问控制,这种访问控制的意思是可以将private、protected限定到X,X可以是包、类,还可以是单例对象

package cn{class UtilsTest{//编译通不过,因为Utils利用private[scala]修饰,只能在scala及其子包中使用//Utils.toString()}package scala{//private[scala]限定Utils只能在scala及子包中使用private[scala] object Utils{def toString(x:String){println(x)}import cn.scala.xtwy._def getTeacher():Teacher=new Teacher("john")}package xtwy{class Teacher(var name:String) {def printName()={Utils.toString(name)}}}}
}
object appDemo{import cn.scala._import cn.scala.xtwy._def main(args: Array[String]): Unit = {//编译通不过,同UtilsTest//Utils.toString(new Teacher("john").name)new Teacher("john").printName() }}

private[this],限定只有该类的对象才能访问,称这种成员为对象私有成员

package cn.scala.xtwy;class Teacher(var name: String) {private[this] def printName(tName:String="") :Unit= { println(tName) }//调用private[this] printName方法def print(n:String)=this.printName(n)
}object Teacher{//private[this]限定的成员,即使伴生对象Teacher也不能使用//def printName=new Teacher("john").printName()
}object appDemo {def main(args: Array[String]): Unit = {//编译不能通过//new Teacher("john").printName()}}

private,定义的类及伴生对象可以访问

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{//伴生对象可以访问def printName=new Teacher("john").printName()
}object appDemo {def main(args: Array[String]): Unit = {//不能访问//new Teacher("john").printName()}}

下面给出的是访问规则表

修饰符 访问范围
无任何修饰符 任何地方都可以使用
private[scala] 在定义的类中可以访问,在scala包及子包中可以访问
private[this] 只能在定义的类中访问,即使伴生对象也不能访问团
private 在定义的的类及伴生对象中可以访问,其它地方不能访问
protected[scala] 在定义的类及子类中可以访问,在scala包及子包中可以访问,
protected[this] 只能在定义的类及子类中访问,即使伴生对象也不能访问
protected 在定义的类及子类中访问,伴生对象可以访问,其它地方不能访问

包对象

包对象主要用于将常量、工具函数,使用时直接通过包名引用

//下面的代码给出了包对象的定义
package cn.scala.xtwy//利用package关键字定义单例对象
package object Math {val PI=3.141529val THETA=2.0val SIGMA=1.9
}class Coputation{def computeArea(r:Double)=Math.PI*r*r
}

上述代码编译后会生成下列文件:

对应字节码文件如下:

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$();
}

不能看出,它为我们的包对象Math创建了一个文件夹,然后创建了两个类,通过单例的方式实现方法调用。

import高级特性

1 隐式引入
在集合那一讲,我们提到,如果不引入任何包,scala会默认引入java.lang._
scala._
Predef._
包中或对象中所有的类和方法,称这种引入会隐式引入

2 重命名

scala中允许对引入的类或方法进行重命名,如果我们需要在程序中同时使用java.util.HashMap及scala.collection.mutable.HashMap时,可以利用重命名的方法消除命名冲突的问题,虽然也可以采用包名前缀的方式使用,但代码不够简洁

//将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

内部类

前面我们提到过内部类,我们看到内部类可以像类的其它成员一样访问外部类的私有成员,本小节将对内部类进行更加详细的介绍。

要点1:外部类不能访问内部类的成员域,但内部类可以直接访问外部类成员域,哪怕这个成员域是private私有的

class OuterClass {//即使定义为 private[this] var x:Int=0,也是可行的private var x:Int=0//def getInnerY=y,外部类不能直接访问内部类的成员域class InnerClass{private var y:Int=0//内部的类可以直接访问外部类的成员变量和成员方法,注意外部类的成员变量是privatedef getOuterX= x}
}object AppDemo{def main(args: Array[String]): Unit = {val o=new OuterClass//创建内部类对象,通过o.InnerClass方式,InnerClass就像是OuterClass的成员变量一样val i=new o.InnerClassprintln(i.getOuterX)}
}

从上述代码可以看出,内部类除了是一个类之外,与外部类的成员没有任何区别,它可以与外部类的成员域一样被使用。

Scala入门到精通——第八节 包和引入相关推荐

  1. Scala入门到精通——第二十七节 Scala操纵XML

    本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种非常重要的半结构化数据表示方式,目前大量的应用依赖于X ...

  2. Scala入门到精通——第二十八节 Scala与JAVA互操作

    本节主要内容 JAVA中调用Scala类 Scala中调用JAVA类 Scala类型参数与JAVA泛型互操作 Scala与Java间的异常处理互操作 1. JAVA中调用Scala类 Java可以直接 ...

  3. Scala入门到精通——第十八节 隐式转换与隐式参数(一)

    本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...

  4. Scala入门到精通——第三十节 Scala脚本编程与结束语

    本节主要内容 REPL命令行高级使用 使用Scala进行Linux脚本编程 结束语 1. REPL命令行高级使用 在使用REPL命令行时,有时候我们需要粘贴的代码比较大,而普通的粘贴可能会些一些问题, ...

  5. Scala入门到精通——第二十四节 高级类型 (三)

    本节主要内容 Type Specialization Manifest.TypeTag.ClassTag Scala类型系统总结 在Scala中,类(class)与类型(type)是两个不一样的概念. ...

  6. Scala入门到精通——第二十节 类型参数(二)

    本节主要内容 Ordering与Ordered特质 上下文界定(Context Bound) 多重界定 类型约束 1. Ordering与Ordered特质 在介绍上下文界定之前,我们对Scala中的 ...

  7. Scala入门到精通——第十四节 Case Class与模式匹配(一)

    本节主要内容 模式匹配入门 Case Class简介 Case Class进阶 1. 模式匹配入门 在Java语言中存在switch语句,例如: //下面的代码演示了java中switch语句的使用 ...

  8. Scala入门到精通——第四节 Set、Map、Tuple、队列操作实战

    本节主要内容 mutable.immutable集合 Set操作实战 Map操作实战 Tuple操作实战 队列操作实战 栈操作实战 mutable.immutable集合 以下内容来源于Scala官方 ...

  9. Scala入门到精通——第二十九节 Scala数据库编程

    本节主要内容 Scala Mavenproject的创建 Scala JDBC方式訪问MySQL Slick简单介绍 Slick数据库编程实战 SQL与Slick相互转换 本课程在多数内容是在官方教程 ...

最新文章

  1. ueditor初始化
  2. linux cat EOF 变量自动解析问题
  3. Python defaultdict 模块和 namedtuple 模块 1
  4. 数据科学 IPython 笔记本 7.5 数据索引和选择
  5. SCCM 2012 简体中文正式版 部署文档 01 环境说明
  6. asp.net支持多文件上传的服务器控件
  7. HFSS19 官方中文教程系列 L03
  8. 卡巴斯基正版半年注册码申请
  9. 用java操作MySQL编写的高校水电费管理系统
  10. java uml模型图 常见图形含义_uml图六种箭头的含义
  11. box-sizing: border-box的作用
  12. 用户分层之RFM模型
  13. 外卖产品(饿了么、美团外卖、百度外卖)竞品分析
  14. 泡泡堂、QQ堂游戏通信架构分析
  15. 高等数学上:函数的极限(重难点)
  16. web服务器的选择 讨论
  17. Matlab-算术编码
  18. Spring缺少aspectjweaver.jar异常
  19. 用c语言简单办法做一个字典_如何用c语言做一个简单的英语词典
  20. 图论(八)——割边割点和块

热门文章

  1. 【终极方法】This method must return a result of type boolean
  2. 解题报告+优化——试题 基础练习 矩形面积交——16行代码AC
  3. Apache服务日志分割(rotatelogs、cronolog)
  4. OpenStack的部署T版(六)——Neutron组件
  5. KVM虚拟化的简单概论
  6. java 虚拟机_浅谈Java虚拟机内存区
  7. “非”天才女程序员的人生
  8. c 语言中浮点数舍入,浮点数在C中舍入,我不明白为什么
  9. 独占一行 html_HTML基础-语义化标签
  10. linux 误删除mysql表能恢复吗,Linux中误删除数据文件和归档日志的恢复方法