**### 方法
基本说明:
Scala中的方法其实就是函数,声明规则请参考函数式编程中的函数声明.
基本语法:
def 方法名(参数列表)[:返回值类型]={
方法体
}
方法的调用机制原理
1. 当我们Scala开始执行时,先在栈区开辟一个main栈,main栈是最后被销毁的
2. 当scala程序在执行到一个方法时,总会开一个新的栈
3. 每个栈是独立的空间,变量(基本数据类型)是独立的,相互不影响(引用类型除外)
4. 当方法执行完毕后,该方法开辟的栈就会被JVM回收( )
构造器
基本介绍:
构造器(constructor) 又叫构造方法,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化
1. java构造器基本语法
[修饰符] 方法名 (参数列表){
构造方法体
}
1.1 回顾-Java构造器的特点
1.在Java中一个类可以定义多个不同的构造方法,构造方法重载
2.如果程序员没有定义构造方法,系统会自动给类生成一个默认无参构造方法(也叫默认构造器),比如Person(){}
3.一旦定义了自己的构造方法(构造器),默认的构造方法就覆盖了,就不能再使用默认的无参构造方法,除非显示的定义一下即:Person(){};
Scala构造器的介绍
和java一样,Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法.(Scala中构造器也支持重载 )
Scala类的构造器包括:主构造器和辅助构造器
Scala构造器的基本语法
class 类名(形参列表){//主构造器
//类体
def this(形参列表){//辅助构造器
}
def this(形参列表){//辅助构造器可以有多个...}
}
1. 辅助构造器 函数的名称this,可以有多个 ,编译器通过不同参数来区分
Scala构造器注意事项和细节
1. Scala构造器作用是完成对新对象的初始化,构造器没有返回值
2. 主构造器的声明直接放置于类名之后
3. 主构造器会执行类定义中的所有语句,这里可以体会到Scala的函数式编程和面向对象编程融合在一起,即:构造器也是方法(函数),传递参数和使用方法和前面的函数部分内容没有区别
4. 如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小扩号可以省略
5. 辅助构造器名称为this(这个和Java不一样的),多个辅助构造器通过不同参数列表进行区分,在底层就是Javaf的构造器重载
6. 辅助构造器,必须在第一行显示地调用主构造器(直接或间接)
6.1 scala朱支持辅助构造器,直接调用父类构造器
```
def this(name:String){
this("jack",10)
this.name=name
}
```
案例:
package Day04
object Rect {
def main(args: Array[String]): Unit = {
val rect = new Rect
rect.printRect(5,3)
}
}
class Person1(){
var name:String= _
var age :Int = _
def this(name:String)={
//辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑
//而且需要放在辅助构造器的第一行[这点和Java一样,Java中一个构造器要调用同类的其他构造器,也需要放在第一行
this()
this.name=name
}
def this(name:String,age:Int){
this()//直接调用主构造器
this.name=name
this.age=age
}
def this(age:Int){
//简介调用主构造器,因为def this(name:String)中调用了主构造器
this("匿名")
this.age=age
}
}
class Rect{
def printRect(m:Int,n:Int)={
for(i<-0 until m){
println("*"*n)
}
}
}
6. 如果想让主构造器编程私有的,可以在()之前加上private,这样用户只能通过辅助构造器来构建对象了
class Person private(){
...
}
7. 辅助构造器的声明不能和主构造器的声明一致,会发生错误
属性高级
构造器参数:
1. Scala类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量.
class Preson(name:String){
}
2. 如果参数使用val关键字声明,那么Scala会将参数作为类的私有的只读属性使用.
3. 如果参数使用var关键字声明,那么Scala会将参数作为类的成员属性使用,并会提供属性对应的xxx()[类似getter/xxx_$eq()[类似setter]方法,即这时的成员属性是私有的,但是可以读写
案例:
def main(args: Array[String]): Unit = {
//val rect = new Rect
// rect.printRect(5,3)
val worker = new Worker("wmith")
worker.name//不能访问inName
val worker2 = new Worker2("wmith")
worker2.name
worker2.inName//可以访问inName
new Worker3("jack")
}
}
//1. 如果主构造是Worker(inName:String),那么inName就是一个局部变量
class Worker (inName:String){
var name=inName
}
//2. 如果主构造器是Worker2(val inName:String),那么inName就是Worker的一个private
//的只读属性
//反编译:
/**
* private final String inName;
* public String inName(){
* return this.inName;}
*/
class Worker2 (val inName:String){
var name=inName
}
//3. 如果主构造器是Worker2(val inName:String),
// 那么inName就是Worker的一个private的可读写属性
class Worker3 (var inName:String){
var name=inName
}
Bean属性
JavaBeans规范定义了Java的属性是想getXxx()和SetXxx()的方法,许多Java工具(框架)都依赖这个命名习惯,为了Java的互操作性,将Scala字段加@BeanProperty,这样会自动生成规范的setXxx/getXxx方法,这时可以使用对象.setXxx()和对象.getXxx()来调用属性.
注意:
给某个属性加入@BeanProperty注解后,会生成getXxx和setXxx的方法并且对原来底层自动生成类似xxx(),xxx_$eq()方法,没有冲突,二者可以共存
import scala.beans.BeanProperty
class Car{
@BeanProperty var name:String=null
}
object BeanPropertyDemo {
def main(args: Array[String]): Unit = {
val car = new Car
//使用@BeanProperty 自动生成 getXxx 和SetXxx
car.setName("奔驰")
}
}
class Car{
@BeanProperty var name:String= _
}
对象创建流程
class Person {
var age: Int = _
var name: String = _
def this(name: String, age: Int) {
this()
this.name = name
this.age = age
}
}
val p: Person = new Person("hel", 12)
Scala对象创建 流程分析
1. 加载类的信息,(属性信息,方法信息(存入栈中)
2. 在内存中(堆)开辟空间
3. 先使用父类主构造,副构造(进行初始化)
4. 使用主构造器对属性进行初始化[age=0,name=null]
5. 使用辅助构造器对属性进行初始化[age=10,name="hello"]
6. 将开辟的对象的地址赋给p这个引用
Java包的三大作用
1. 区分相同名字的类
2. 当类很多时,可以很好的管理类
3. 控制访问范围
Java对包的要求
1. 类的源文件,需要和包对应的文件路径匹配
2. 当我们编译Dog类,后生成对应的.class文件,编译器会将.class文件也放在和包对应的文件路径下
Scala包的基本介绍
和Java一样,Scala中管理可以使用包,但Scala中的包的功能更加强大,使用也相对复杂些,
Scala包快速入门
1. 使用打包技术解决上面的问题,
//使用xh的tiger
val t1 = new Day04.xh.Tiger
//使用xm的tiger
val t2 = new Day04.xm.Tiger
}
Scala包的特点概述
基本语法:
package 命名
Scala包的三大作用:
1. 区分相同名字的类
2. 当类很多时,可以很好的管理类
3. 控制访问范围
4. 可以对类的功能进行扩展
注意:
Scala中包名和源码所在的系统文件目录结构要可以不一致,但是编译后的字节码文件路径和包名会保持一致(这个工作由编译器完成)
Scala包的命名
命名规则:
只能包含数字,字母,下划线,小圆点,但不能用数字开头,也不要使用关键字.
demo.class.exec1//错误,因为class是关键字
demo.12a//错误,因为内不能使用数字作为关键字
命名规范:
com.公司名,项目名,业务模块名
Scala会自动引入的常用包
java.lang.*
scala包不代表子包
Predef包
Ctrl+B==>查看包的内容
Scala 包注意事项和使用细节
1. Scala进行package打包时,可以有如下形式 // 传统方式
1.1 package com.iflytek.scala // 和第一种完全等价
1.2 package com.iflytek
1.2 package scala
1.3 package com.iflytek{
1.3 package scala{}}
2. 包也可以像嵌套类那样使用(包中有包),这个在前面的第三种打包方式已经讲过,在使用第三种方式时的好处是:程序员可以在同一个文件中,将类(class/object),trait创建在不用的包中,这样就非常灵活了
3. 作用域原则:
可以直接向上访问.即:Scala中子包直接访问父包中的内容,大括号体现作用域.
提示(Java中子包使用父包类重名时,默认采用就近原则,如果希望指定使用某个类,则带上包名即可)
4. 父包要访问子包的内容时,需要import对应的类等.import在scala中任何位置不受限制.
5. 可以在容一个.scala文件中,声明多个并列的package(建立嵌套的package不要超过3层)
6.1 使用相对路径,使用绝对路径_root_.scala(sless)当包名冲突时使用
包对象
基本介绍:
包可以包含类,对象和特质(trait),但不能包含函数/方法或变量的定义,为了弥补这一点不足,scala提供了包对象的概念来解决这个问题
1. 在包中直接写方法,或者定义变量,就错误==>,使用包对象的技术来解决
2. package object scala 表示创建一个包对象 scala,它是com.filytek.sclaa这个包对应的包对象
3. 每一个包都可以有一个包对象
4. 包对象的名字需要和子包一样
5. 在包对象中可以定义变量,方法
6. 在包对象中定义的变量和方法,就可以在对应的包中使用
package scala {
//表示在 com.iflytek.scala包下创建类p1
class p1 {
var name: String = _
var age: Int = _
}
/
var name="hell"// 不支持
}
案例:
import Day04.xh9la.scala.p1
// com.iflytek.scala ,还可以写特质trait,类,还可以写object
//2. 即scala支持,在一个文件中,可以同时创建多个包,以及给各个包创建类,trait和object
package object scala {
var name = "hell"
}
package scala {
//表示在 com.iflytek.scala包下创建类p1
class p1 {
var name1: String = _
var age: Int = _
def sayHello(): Unit = {
println(name)
}
}
}
object PackageDemo {
def main(args: Array[String]): Unit = {
val p = new p1
p.sayHello()
}
}
包对象的底层实现机制分析
7. 在底层这两个包对象会生成两个类,package.class 和package$.class
1. 当创建对象后,在该包下生成public final class package 和public final class package$
2. 通过package$的一个静态实例完成对包对象中的属性和方法的调用.
package object scala{
val name= "King"
def sayHi(){
println("hi")
}
}
1. 生成package.class
publi final class scala{
public static void sayHiv(){
package..MODULE.sayHi();
}
}
public class temp{
public static void main(String args[]){
sysout()...
package$$.MODOULES$.sayOk();//调用package$里面的一个实例
}}
final class package${
public static final package$$ MODULES$;
private final String name = "ok";
static{
MODULE$ = new package$$();
public void sayOk(){
sysout()...
public String name(){return this.name}
}
}
}
回顾java访问修饰符基本介绍
前言:java提供四种访问控制修饰符号,控制方法和变量的访问权限(范围);
1. 公开级别:用public修饰,对外公开
2. 受保护级别:用protected修饰,对子类和同一个包中的类公开
3. 默认级别:没有修饰符号,向同一个包的类公开
4. 私有级别:用private修饰,只有类本身可以访问,不对外公开
当一个文件中同时出现class clerk 和object clerk
1. class clerk 称为伴生类
2. object clerk 称为伴生对象
3. 因为scala抛弃了static,它就是设计了伴生类和伴生对象的概念中
4. 伴生类 写非静态的内容 伴生对象 就是静态内容
scala中包的可见性和访问修饰符的使用
1. 当属性访问权限为默认时,从底层看属性是private,但是因为提供了xxx——$eq()[类似setter()]/XXX()[类似getter()]方法,因此从使用效果看是任何地方都可以访问。
2. 当方法权限为默认时,默认为public访问权限。
3. private 为私有权限,只在类的内部和伴生对象中可以用
4. protected 受保护权限,比Java更严格,只能子类访问同包无法访问。
5. scala中没有public,即不能使用public显示的修饰属性和方法
6. 包访问权限(表示属性有了限制,同时包也有了限制),这点和java不一样
当private 修饰的属性不能用时,可以使用包访问扩大权限,相当于扩大访问范围
private[visit] val name = ""
scala引入包基本介绍
1. scala引入包也是使用import,基本的原理和机制和java一样,但是Scala中的import功能更加强大,也更灵活
2. 因为Scala语言源自于Java,所以java.lang包中的类会自动引入到当前环境中,而Scala中的scala包和Predef包的类也会自动引入当前环境中,即其下面的类可以直接使用,
3. 如果想要
Scala引入包的细节和注意事项
1. 在Scala中,import语句可以出现在任何地方,并不仅限于文件顶部,import语句的作用一直延伸到包含该语句的块末尾,这种语法的好处是:在需要时再引入包,缩小import包的作用范围,提高效率
2. java中如过想要引入包中所有的类,可以通过通配符*,Scala中采用_(_表示将该包的所有内容引入)
3. 如果不想要某个包中全部的类,而是其中的几个类,可以使用选取器(大括号)
import scala.collection.mutable.[HashMap,HashSet]
4. 如果引入的多个包中含有相同的类,那么可以将不需要的类进行重命名进行区分,这个就是重命名.
import java.util.{HashMap>java.HashMap,List}
5. 如果某个冲突的类根本不会用到,那么这个类可以直接隐藏掉,
面向对象编程--抽象
1. 我们在前面定义一个类的时候,实际上就是把一类事物的共有属性和行为提取出来,形成一个物理模型(模板),这种研究问题的方法称为抽象
面向对象编程--封装
1. 封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作
2. 好处:
1. 隐藏实现细节
2. 可以对数据进行验证,保证安全合理
3. 同时可以加入业务逻辑
3. 如何体现封装
1. 对类中的属性进行封装
2. 通过成员方法,包实现封装
4. 实现步骤
1. 属性私有化
2. 提供一个公共的set方法,用于对属性进行获取,设置