Scala入门到精通——第八节 包和引入
本节主要内容
- 包的作用与定义
- 包的作用域与引入(import)的使用方法
- 访问控制
- 包对象
- import高级特性
- 内部类
包的作用与定义
同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入门到精通——第八节 包和引入相关推荐
- Scala入门到精通——第二十七节 Scala操纵XML
本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种非常重要的半结构化数据表示方式,目前大量的应用依赖于X ...
- Scala入门到精通——第二十八节 Scala与JAVA互操作
本节主要内容 JAVA中调用Scala类 Scala中调用JAVA类 Scala类型参数与JAVA泛型互操作 Scala与Java间的异常处理互操作 1. JAVA中调用Scala类 Java可以直接 ...
- Scala入门到精通——第十八节 隐式转换与隐式参数(一)
本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...
- Scala入门到精通——第三十节 Scala脚本编程与结束语
本节主要内容 REPL命令行高级使用 使用Scala进行Linux脚本编程 结束语 1. REPL命令行高级使用 在使用REPL命令行时,有时候我们需要粘贴的代码比较大,而普通的粘贴可能会些一些问题, ...
- Scala入门到精通——第二十四节 高级类型 (三)
本节主要内容 Type Specialization Manifest.TypeTag.ClassTag Scala类型系统总结 在Scala中,类(class)与类型(type)是两个不一样的概念. ...
- Scala入门到精通——第二十节 类型参数(二)
本节主要内容 Ordering与Ordered特质 上下文界定(Context Bound) 多重界定 类型约束 1. Ordering与Ordered特质 在介绍上下文界定之前,我们对Scala中的 ...
- Scala入门到精通——第十四节 Case Class与模式匹配(一)
本节主要内容 模式匹配入门 Case Class简介 Case Class进阶 1. 模式匹配入门 在Java语言中存在switch语句,例如: //下面的代码演示了java中switch语句的使用 ...
- Scala入门到精通——第四节 Set、Map、Tuple、队列操作实战
本节主要内容 mutable.immutable集合 Set操作实战 Map操作实战 Tuple操作实战 队列操作实战 栈操作实战 mutable.immutable集合 以下内容来源于Scala官方 ...
- Scala入门到精通——第二十九节 Scala数据库编程
本节主要内容 Scala Mavenproject的创建 Scala JDBC方式訪问MySQL Slick简单介绍 Slick数据库编程实战 SQL与Slick相互转换 本课程在多数内容是在官方教程 ...
最新文章
- ueditor初始化
- linux cat EOF 变量自动解析问题
- Python defaultdict 模块和 namedtuple 模块 1
- 数据科学 IPython 笔记本 7.5 数据索引和选择
- SCCM 2012 简体中文正式版 部署文档 01 环境说明
- asp.net支持多文件上传的服务器控件
- HFSS19 官方中文教程系列 L03
- 卡巴斯基正版半年注册码申请
- 用java操作MySQL编写的高校水电费管理系统
- java uml模型图 常见图形含义_uml图六种箭头的含义
- box-sizing: border-box的作用
- 用户分层之RFM模型
- 外卖产品(饿了么、美团外卖、百度外卖)竞品分析
- 泡泡堂、QQ堂游戏通信架构分析
- 高等数学上:函数的极限(重难点)
- web服务器的选择 讨论
- Matlab-算术编码
- Spring缺少aspectjweaver.jar异常
- 用c语言简单办法做一个字典_如何用c语言做一个简单的英语词典
- 图论(八)——割边割点和块
热门文章
- 【终极方法】This method must return a result of type boolean
- 解题报告+优化——试题 基础练习 矩形面积交——16行代码AC
- Apache服务日志分割(rotatelogs、cronolog)
- OpenStack的部署T版(六)——Neutron组件
- KVM虚拟化的简单概论
- java 虚拟机_浅谈Java虚拟机内存区
- “非”天才女程序员的人生
- c 语言中浮点数舍入,浮点数在C中舍入,我不明白为什么
- 独占一行 html_HTML基础-语义化标签
- linux 误删除mysql表能恢复吗,Linux中误删除数据文件和归档日志的恢复方法