版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
11.Scala的变量及函数一、Scala变量定义二、Scala的基本类型三、函数及其几种形式目
录22一、Scala变量定义31.2如何定义一个变量定义一个变量时,需要在变量名前面添加关键字“var”或者“val”;“var”定义的变量,可以重新赋予新的值,并且重新赋值时不需要加“var”;“val”定义的变量,则禁止被重新赋值。一、Scala变量定义41.1变量名的形式Scala推荐使用“驼峰命名法”变量名可以是任意的字母、数字和下划线的组合,但是不能以数字开头例如,“valisOne”,“classMyClass”一、Scala变量定义51.2.1合法变量定义在首次定义变量时,就必须赋予具体的值来初始化。一、Scala变量定义scala>valx
x=1
scala>varx
x=1scala>valx=1
x:Int=1
scala>valmsg="Hello,world!"
msg:String=Hello,world!错误定义!!!正确定义形式61.2.2“var”和“val”定义案例一、Scala变量定义val类型的变量则直接禁止重新赋值。var类型的变量在重新赋值时,新值必须和旧值是同一个类型,否则会发生类型匹配错误。scala>valx=1
valx:Int=1
scala>x=10scala>varx=1
x:Int=1
scala>x=10
scala>x="abc"71.2.3其余变量定义案例一、Scala变量定义赋给多个变量相同的值,在一条语句里用逗号间隔的变量名即可,不必逐条定义。Scala变量定义具有覆盖性。scala>vala,b,c=1
a:Int=1
b:Int=1
c:Int=1scala>valx=1
valx:Int=1
scala>valx=10
valx:Int=10
scala>x
valres0:Int=10
81.3注意事项赋给变量的对象存在可变与不可变之分。即分清楚是变量指向的对象本身发生了改变,还是变量指向了新的对象。Scala提倡定义val类型的变量,因为它是函数式编程,而函数式编程的思想之一就是传入函数的参数不应该被改变。Scala也允许指令式编程,因而预留了var类型的变量,尽管并不推荐使用。一、Scala变量定义9二、Scala的基本类型102.1基本类型二、Scala的基本类型Scala标准库定义了九种基本类型,如下表所示。除了“String”类型在java.lang包之外,其余都在Scala的包里。Scala的基本类型Byte8-bit有符号整数,补码表示,范围是-27到27-1Short16-bit有符号整数,补码表示,范围是-215到215-1Int32-bit有符号整数,补码表示,范围是-231到-231-1Long64-bit有符号整数,补码表示,范围是-263到-263-1Char16-bit无符号字符,Unicode编码,范围是0到216-1String字符串Float32-bit单精度浮点数,符合IEEE754标准Double64-bit双精度浮点数,符合IEEE754标准Boolean布尔值,其值为true或者false112.2定义变量类型二、Scala的基本类型Scala的编译器具有自动推断变量类型的功能。如果要显式声明变量的类型,或者无法推断时,则只需在变量名后面加上一个冒号“:”,然后在等号与冒号之间写出类型名即可。scala>valx:Int=123
valx:Int=123
scala>valy:String="123"
valy:String=12312二、Scala的基本类型2.3三种字面量整数字面量整数默认情况下推断为Int类型。而Byte和Short则需要定义变量时显式声明。结尾有l或者L为Long类型。默认是十进制,若以“0x”或者“0X”开头,则被认为是十六进制。scala>vala=100
a:Int=100scala>vald=200L
d:Long=200scala>valb=0X123Abc
b:Int=1194684valc:Byte=15
c:Byte=15不能超过类型的表示范围!13二、Scala的基本类型2.3三种字面量浮点数字面量都是十进制的,类型默认是Double类型。在末尾添加E和整数来表示10的N次幂。在变量末尾加大小写的D或者F来表示是哪种类型。scala>vala=1.2E3
a:Double=1200.0scala>valb=-3.2f
b:Float=-3.2注意:Double类型的字面量不能赋给Float类型的变量!!!14二、Scala的基本类型2.3三种字面量字符与字符串字面量字符字面量:以单引号包起来的一个字符。可以用‘\u编码号’的方式来构造一个字符。支持转义字符。scala>vala=‘D’
a:Char=Dscala>valb=‘\u0041'
b:Char=Ascala>vald=‘\\’
d:Char=\15二、Scala的基本类型2.3三种字面量字符与字符串字面量字符串字面量:用双引号“
”包起来的字符序列,长度任意。允许掺杂转义字符。scala>vala="\\\\\\"
a:String=\\\162.4字符串插值二、Scala的基本类型字符串插值使表达式可以被嵌入字符串字面量中并被求值。第一种形式是s插值器,即在字符串的双引号前加一个s,形如s“…${表达式}…”。识别转义字符。scala>valname="ABC"
name:String=ABC
scala>println(s"$nameDEFG")
ABCDEFGscala>s"Sum=${1+10}"
res0:String=Sum=11scala>s"\\\\"
res1:String=\\172.4字符串插值二、Scala的基本类型第二种形式是raw插值器,与s插值器类似,不识别转义字符。第三种形式是f插值器,允许给内嵌的表达式加上printf风格的指令,指令放在表达式之后并以百分号开始。scala>raw"\\\\"
res2:String=\\\\scala>printf(f"${math.Pi}%.5f")
3.1415918三、函数及其几种形式193.1定义函数三、函数及其几种形式defmax(x:Int,y:Int):Int={
if(x>y)
x
else
y}用“def”开始函数定义函数名参数名及参数类型函数返回结果的类型等号花括号里定义函数体20分号推断代码中语句末尾分号是可选的,编译器会自动推断分号。不会推断出分号的情况:①句末以非法结尾字符结尾;②下一行的句首是以非法起始字符开始;③跨行出现的圆括号对“()”或者方括号对“[]”。建议一行只写一条完整的语句,句末分号省略,让编译器自动推断。3.1定义函数三、函数及其几种形式21函数的返回结果“return”关键字也是可选的。编译器会自动为函数体里的最后一个表达式加上“return”,将其作为返回结果。返回结果的类型根据参数类型和返回的表达式来自动推断。返回结果为Unit,表示没有值返回。如果显式声明为Unit类型的函数,无论如何也不会把表达式的结果返回。3.1定义函数三、函数及其几种形式22等号与函数体函数体是用花括号包起来,包括多条语句,并自动推断分号、返回最后一个表达式。Scala的函数定义还有一个等号,返回类型没有声明时,等号甚至也可以省略。但建议不要省略等号,避免产生不必要的错误,返回类型最好也显式声明。3.1定义函数三、函数及其几种形式23无参函数如果一个函数没有参数,那么可以写一个空括号作参数列表,也可以不写。原则上,无副作用的无参函数省略括号,有副作用的无参函数添加括号,使用时需要注意。3.1定义函数三、函数及其几种形式243.2方法方法其实就是定义在类、对象、特质里面的函数,这种函数叫做“成员函数”或者“方法”,与多数oop(object-orientedprogramming)语言一样。三、函数及其几种形式253.3嵌套函数即在函数内部定义别的函数。这种函数是其外层函数独有,不能被外部调用。参数与外层函数公用。三、函数及其几种形式scala>defaddSub(x:Int,y:Int)={
|defsub(z:Int)=z-10
|if(x>y)sub(x-y)elsesub(y-x)
|}
defaddSub:(x:Int,y:Int)Int
scala>addSub(100,20)
valres0:Int=70263.4函数字面量函数是一等值,也存在字面量。其定义形式为:(参数1:参数1类型,参数2:参数2类型,...)=>{函数体}。其形式为了精简,只保留函数体,并用下划线“_”作为占位符来代替参数。而当函数字面量入参时,其形式为冒号后面加“(参数1类型,参数2类型,...)=>返回结果的类型”。三、函数及其几种形式273.4函数字面量三、函数及其几种形式scala>defaFunc(f:Int=>Int)=f(1)+1
aFunc:(f:Int=>Int)Int
scala>aFunc(x=>x+1)
res1:Int=3举例:283.5部分应用函数“def”定义的函数也有一等值的功能,只不过需要借助部分应用函数的形式来实现。部分应用函数,就是把def函数打包到一个函数值里,使它可以赋给变量,或当作函数参数进行传递。三、函数及其几种形式293.5部分应用函数举例:三、函数及其几种形式scala>defsum(x:Int,y:Int,z:Int)=x+y+z
defsum:(x:Int,y:Int,z:Int)Int
scala>vala1=sum(4,5,6)
vala:Int=15
scala>vala2=sum(4,_:Int,6)
vala2:Int=>Int=$$Lambda$1124/31807844@cc5a39
scala>a2(5)
valres0:Int=15
scala>vala3=sum_
vala3:(Int,Int,Int)=>Int=$$Lambda$1125/7905168@d10d40
scala>a3(4,5,6)
valres1:Int=15303.6闭包一个函数除了可以使用它的参数外,还能使用定义在函数以外的其他变量。函数的参数称为绑定变量,函数以外的变量称为自由变量。函数在运行期间捕获自由变量,让函数闭合,定义明确。这种函数叫闭包。自由变量必须在函数前面定义,否则编译器就找不到,会报错。三、函数及其几种形式313.6闭包三、函数及其几种形式如果捕获了某一变量,后续同名定义,则无法改变已经捕获的值。但是如果是var变量,则闭包会随着改变。varmore=1
valaddMore=(x:Int)=>x+more//addMore=x+1
more=2//addMore=x+2
varmore=10//addMore=x+2
more=-100//addMore=x+2323.7函数的特殊调用形式普通函数调用形式是按参数的先后顺序逐个传递的,但如果调用时显式声明参数名并给其赋值,则可以无视参数顺序。具名参数三、函数及其几种形式scala>defmax(x:Int,y:Int,z:Int)={
|if(x>y&&x>z)println("xismaximum")
|elseif(y>x&&y>z)println("yismaximum")
|elseprintln("zismaximum")
|}
defmax:(x:Int,y:Int,z:Int)Unit
scala>max(1,z=10,y=100)
yismaximum无视参数顺序333.7特殊函数调用形式函数定义时参数一个默认值,如果调用函数时缺省了这个参数,那么就会使用定义时给的默认值。通常和具名参数结合使用。默认参数值三、函数及其几种形式scala>defmax(x:Int=10,y:Int,z:Int)={
|if(x>y&&x>z)println("xismaximum")
|elseif(y>x&&y>z)println("yismaximum")
|elseprintln("zismaximum")
|}
defmax:(x:Int,y:Int,z:Int)Unit
scala>max(y=3,z=5)
xismaximum省略了x参数343.7特殊函数调用形式Scala允许把函数的最后一个参数标记为重复参数,其形式为在最后一个参数的类型后面加上星号“*”。意思是可以在运行时传入任意个相同类型的元素,包括零个。类型为“T*”的参数的实际类型是“Array[T]”。尽管是T类型的数组,但要求传入参数的类型仍然是T。重复参数三、函数及其几种形式353.7特殊函数调用形式重复参数三、函数及其几种形式scala>defaddMany(msg:String,num:Int*)={
varsum=0
for(x<-num)sum+=x
println(msg+sum)
}
defaddMany:(msg:String,num:Int*)Unit
scala>addMany("sum=",1,2,3)
sum=6
scala>addMany("sum=",Array(1,2,3))
error:typemismatch;
found:Array[Int]
required:Int
scala>addMany("sum=",Array(1,2,3):_*)
sum=6举例:363.8柯里化一个函数可以有任意个参数列表。在使用时,当参数列表里只有一个参数时,在调用该函数时允许参数的圆括号改为花括号。三、函数及其几种形式scala>defadd(x:Int,y:Int,z:Int)=x+y+z
defadd:(x:Int,y:Int,z:Int)Int
scala>add(1,2,3)
valres0:Int=6
scala>defaddCurry(x:Int)(y:Int)(z:Int)=x+y+z
defaddCurry:(x:Int)(y:Int)(z:Int)Int
scala>addCurry(1)(2){3}
valres1:Int=6373.9传名参数传名参数是一个无参函数的函数入参,传名参数的类型表示法是“=>函数的返回类型”,相对常规表示法去掉了前面的空括号。在调用该函数时,传递进去的函数字面量则可以只写“函数体”,去掉了“()=>”。传名参数使得代码更加简洁、自然。三、函数及其几种形式383.9
传名参数三、函数及其几种形式varassertionEnabled=false
//predicate是类型为无参函数的函数入参
defmyAssert(predicate:()=>Boolean)=
if(assertionEnabled&&!predicate())
thrownewAssertionError
//常规版本的调用
myAssert(()=>5>3)
//传名参数的用法,因为去掉了空括号,所以调用predicate时不能有括号
defbyNameAssert(predicate:=>Boolean)=
if(assertionEnabled&&!predicate)
thrownewAssertionError
//传名参数版本的调用,看上去更自然
byNameAssert(5>3)39四、总结40掌握Scala定义变量的方法及基本变量类型。理解函数作为一等值的概念,函数字面量的作用以及部分应用函数的作用。对整体的Scala语言有一个较为清楚的认识。四、总结41谢谢大家2021年11月12.Scala面向对象编程一、类和对象二、操作符即方法三、类继承四、特质目录44一、类和对象45面向过程编程类和对象面向对象编程什么是面向对象编程?万物皆对象!医嘱、护士、病人、手、皮肤、血管、消毒水、空气……46面向过程编程类和对象面向对象编程什么是面向对象编程?需求:把大象小胖装进冰箱小冰void小冰开门(){}void小胖进小冰(){}void小冰关门(){}Intmain(){
小冰开门();小胖进小冰();小冰关门();}class冰箱{def开门(){}def关门(){}}class大象{def进入(d:String){}}object大象进冰箱{defmain(args:Array[String]):Unit={val小胖=new大象val小冰=new冰箱
小冰.开门
小胖.进入(小冰)小冰.关门}}47为什么选面向对象编程?面向过程编程ProcedureOriented
一、类和对象面向对象编程
ObjectOriented
///jerry11112/article/details/79027834易维护、易复用、易扩展一些情景下性能比面向对象高48类:一个模板,它描述一类对象的行为和状态。对象:类的一个实例,具体的事物。类是创建对象的模板,对象是类的实例
一、类和对象1.1类🐕类:狗状态:颜色,名字,品种行为:吃,叫,摇尾巴对象2颜色:黑白名字:二毛品种:哈士奇类与对象的概念对象1颜色:黄白名字:大旺品种:中华田园49类里有什么?一、类和对象🐕类:狗字段:颜色,名字,品种方法:吃,叫,摇尾巴1.1类方法:用“def”定义的函数,是对象具有的行为成员构造对象时,操作系统会分配存储给每个对象来放自己的字段,但不需要为某个对象单独保存其方法!字段:val或var类型的变量,保存对象的状态或数据50例如:一、类和对象[修饰符]
class类名{
类体}1.1类一般不加,省略时是默认类具有公有可见的classStudents{
varname="None"
varage:Int=_
varscore:Double=_
defregister(n:String,a:Int,sc:Double):Unit={
name=n
age=a
score=sc
}
}定义类Students申明字段,必须显示的初始化定义方法register定义类51一、类和对象创建对象说明:val类型的变量只能与初始化时的对象绑定,不能再被赋予新的对象。Scala
在创建对象时,类型声明可以省略。一般一个对象的类型,就是这个类。val对象名[:类型]=new
类名()1.1类52一、类和对象访问对象成员对象名.字段名1.1类对象名.方法名scala>classStudents{
|privatevarname="None"
|defregister(n:String)=name=n
|defdisplay()=println(name)
|}
definedclassStudents
scala>valstu=newStudents
stu:Students=Students@15a7e51
scala>stu.register("Bob")
scala>
^
error:variablenameinclassStudentscannotbeaccessedinStudents
scala>stu.display()
Bob只可访问公有的类成员(默认公有),外部不可访问private修饰的类成员创建对象并赋给变量stu调用方法register外部访问字段name53一、类和对象1.2类的构造方法主构造方法不需要显式定义
,类内部非字段、非方法的代码都是“主构造方法”。类名后面可以定义若干个参数列表,用于接收参数,参数将在构造对象时用于初始化字段并传递给主构造方法使用。需求:如果想在创建Sutdents的对象时直接指定这个对象的姓名,该怎么做?
是一种特殊的方法,用于完成对新对象的初始化。构造方法类的构造方法主构造方法辅助构造方法54一、类和对象举例:1.2类的构造方法scala>classStudents(n:String){
|valname=n
|println("Astudentnamed"+n+"hasbeenregistered.")
|}
definedclassStudents
scala>valstu=newStudents("Tom")
AstudentnamedTomhasbeenregistered.
stu:Students=Students@5464eb28主构造方法Students类接收一个String参数n,并用n来初始化字段name主构造方法构造对象时初始化字段name并调用主构造方法55一、类和对象1.2类的构造方法辅助构造方法目的:任何构造方法最终都调用该类的主构造方法,使主构造方法成为类的单一入口。以“defthis(......)”来开头;一个类内可以有多个辅助构造方法,编译器通过不同参数来区分不同的辅助构造方法。第一步行为必须是调用该类的主构造方法或其它的辅助构造方法。字段或方法“当前”所在的对象56一、类和对象举例:以“defthis(......)”开头构造方法通过参数区分第一步调用主构造方法或另一个辅助构造方法请同学们思考在构造stu这个对象时是调用了哪个构造方法呢?scala>classStudents(n:String){
|valname=n
|defthis()=this("None")
|println("Astudentnamed"+n+"hasbeenregistered.")
|}
definedclassStudents
scala>valstu=newStudents
AstudentnamedNonehasbeenregistered.
stu:Students=Students@1cf39c6调用主构造方法辅助构造方法1.2类的构造方法辅助构造方法57一、类和对象举例:在类名与类的参数列表之间加上关键字“private”,那么主构造方法就是私有的。scala>classStudentsprivate(n:String,m:Int){
|valname=n
|valscore=m
|defthis(n:String)=this(n,100)
|println(n+"'sscoreis"+m)
|}
definedclassStudents
scala>valstu=newStudents("Bill",90)
^
error:toomanyarguments(2)forconstructorStudents:(n:String)Students
scala>valstu=newStudents("Bill")Bill'sscoreis100
stu:Students=Students@4c3ed51.2类的构造方法私有主构造方法外部代码构造对象时不能通过主构造方法进行,而必须使用其他公有的辅助构造方法或工厂方法(专门用于构造对象的方法)58一、类和对象1.3类参数类参数也是主构造方法的形参无修饰符修饰:仅仅是参数,一个局部变量。val或var修饰:在类的内部会生成一个与参数同名的公有字段,
构造对象时,这些参数会直接复制给同名字段。classPerson(valsex:String){
}sex不仅仅是参数还是类的公有字段,相当于在类内定义了valsex,其值可以在构造对象时被传入59一、类和对象1.3类参数举例:scala>classStudents(valname:String,varscore:Int){
|defexam(s:Int)=score=s
|overridedeftoString=name+"'sscoreis"+score+"."
|}
definedclassStudents
scala>valstu=newStudents("Tim",90)
stu:Students=Tim'sscoreis90.
scala>stu.exam(100)
scala>stu.score
res0:Int=100不仅为类参数,还是类成员可以在外部通过对象访问60一、类和对象1.4方法重载方法重载:在类里定义了多个同名的方法,但是每个方法的参数不一样。这些方法虽然同名,但是它们是不同的。方法重载是面向对象里多态属性的一种表现。classAdder{
defadd(a:Int,b:Int){
varsum=a+b
println(sum)
}
defadd(a:Int,b:Int,c:Int){
varsum=a+b+c
println(sum)
}
}在Adder类中有两个版本的add方法61一、类和对象1.5单例对象与伴生对象单例对象:用“object”开头定义一个对象。伴生对象、伴生类:单例对象&同名类C++、Java等语言:类内可以有静态变量(不属于某个对象,是所有对象共有的)Scala:纯粹的面向对象属性,无静态操作的概念为什么会有单例对象?存放静态变量和方法作为程序的入口打包某方面功能的函数系列成为一个工具集伴生类和伴生对象必须在同一个文件里,两者可以互访对方的所有成员。单例对象的作用62一、类和对象1.6工厂对象与工厂方法工厂方法:专门用来构造某一个类的对象的方法。工厂对象:包含这些工厂方法集合的单例对象。用法:工厂方法通常定义在伴生对象里。尤其是当一系列类存在继承关系时,可以在基类的伴生对象里定义一系列对应的工厂方法。作用:不用直接使用new来实例化对象,改用方法调用。对外隐藏了类的实现细节!63一、类和对象1.6工厂对象与工厂方法//students.scala
classStudents(valname:String,varscore:Int){
defexam(s:Int)=score=s
overridedeftoString=name+"'sscoreis"+score+"."
}
objectStudents{
defregisterStu(name:String,score:Int)=newStudents(name,score)
}将文件students.scala编译后,在解释器中可以这样使用:scala>importStudents._
importStudents._
scala>valstu=registerStu("Tim",100)
valstu:Students=Tim'sscoreis100.导入单例对象调用工厂方法来构造Students类的对象类Students的伴生对象,即工厂对象工厂方法64一、类和对象1.7apply方法用法:在伴生对象里定义名为apply的工厂方法,就能通过“伴生对象名(参数)”来构造一个对象。在类里定义一个与类相关的、具有特定行为的apply方法,让使用者可以隐式调用,进而隐藏相应的实现细节。对象.apply(参数)显式调用对象(参数)隐式调用如果apply是无参方法,必须写出空括号!类和单例对象,都能定义apply方法65一、类和对象1.7apply方法//students2.scala
classStudents2(valname:String,varscore:Int){
defapply(s:Int)=score=s
defdisplay()=println("Currentscoreis"+score+".")
overridedeftoString=name+"'sscoreis"+score+"."
}
objectStudents2{
defapply(name:String,score:Int)=newStudents2(name,score)
}将文件students2.scala编译后,就能在解释器里这样使用:scala>valstu2=Students2("Jack",60)
valstu2:Students2=Jack'sscoreis60.
scala>stu2(80)
scala>stu2.display()
Currentscoreis80.用伴生对象的工厂方法来构造对象类中定义apply方法伴生对象中定义apply的工厂方法调用类中apply方法66一、类和对象1.8小结面向对象编程的思想类、对象、方法、字段的概念和定义的语法类参数的概念、用类的构造方法来构造对象单例对象与伴生对象工厂对象与工厂方法apply方法67二、操作符即方法682.1操作符在Scala里的解释基本类型:byte、short、int、char、float等操作符:+、-、*等二、操作符即方法C++、Java等“classByte”、“classShort”、“classChar”、“classInt”、“classLong”、“classFloat”、“classDouble”、“classBoolean”和“classUnit”九种值类定义在“classInt”、“classDouble”等类里的成员方法Scala追求纯粹的面向对象,万物皆对象!抽象的、不可继承的、对象由字面量表示692.1操作符在Scala里的解释二、操作符即方法Int对象“1”调用了它的成员方法“+”,并把Int对象“2”当作参数传递给了该方法,最后这个方法会返回一个新的Int对象“3”1+21.+(2)scala>classStudents3(valname:String,varscore:Int){
|defexam(s:Int)=score=s
|deffriends(n:String,s:Int)=println("Myfriend"+n+"gets"+s+".")
|overridedeftoString=name+"'sscoreis"+score+"."
|}
classStudents3
scala>valstu3=newStudents3("Alice",80)
valstu3:Students3=Alice'sscoreis80.
scala>stu3exam100
scala>stu3.score
valres0:Int=100
scala>stu3friends("Bob",70)
MyfriendBobgets70.方法调用都能写成操作符的形式:去掉句点符号,并且方法参数只有一个时可以省略圆括号。70二、操作符即方法2.2三种操作符前缀操作符写在操作数前面操作数只有一个一个无参方法,操作数是调用该方法的对象前缀操作符只有“+”、“-”、“!”和“~”四个,相对应的方法名分别是“unary_+”、“unary_-”、“unary_!”和“unary_~”;如果自定义的方法名是“unary_”加上这四个操作符之外的操作符,那么就不能写成前缀操作符的形式。eg.定义了方法“unary_*”*p
p.unary_*
punary_*×√√71二、操作符即方法2.2三种操作符中缀操作符左右两边都接收操作数两个操作数中的一个是调用该方法的对象,一个是传入该方法的参数普通的有参方法参数那一边没有数量限制,只是多个参数需要放在圆括号里;以冒号“:”结尾的操作符,其右操作数是调用该方法的对象,其余操作符都是把左操作数当调用该方法的对象。72二、操作符即方法2.2三种操作符后缀操作符写在操作数后面的操作符并且操作数只有一个,即调用该方法的对象无参方法方法名如果构成前缀操作符的条件,那么既可以写成前缀操作符,也可以把完整的方法名写成后缀操作符。方法是“unary_+”、“unary_-”、“unary_!”和“unary_~”732.3操作符的优先级和结合性二、操作符即方法优先级通过方法名的首个字符来比较优先级前缀操作符的方法名要去掉关键字圆括号内的优先级最高1+++2***31+++(2***3)742.3操作符的优先级和结合性二、操作符即方法优先级如果操作符以等号结尾,并且不是“>=”、“<=”、“==”或“!=”四个比较操作符之一,那么就认为是赋值操作符,优先级最低。sum*=1+2sum*=(1+2)例外“*=”的优先级并不会因为以“*
”开头就比“+”高,而是被当作了一种赋值操作752.3操作符的优先级和结合性二、操作符即方法结合性一般情况,同级的操作符:从左往右结合以冒号结尾的中缀操作符:从右往左结合a+b+c+d((a+b)+c)+da:::b:::c:::da:::(b:::(c:::d))例如:好的编程习惯:在操作符的结合顺序不能一眼就看明白时,最好加上圆括号来表示前后顺序!762.4预设操作符二、操作符即方法+算术加法-算术减法*算术乘法/算术除法%算术取余>
大于<
小于>=大于等于<=小于等于==等于!=不等于&&、&逻辑与,前者短路,后者不短路||、|逻辑或,前者短路,后者不短路!逻辑非&位与|位或^位异或~位取反>>
算术右移<<
左移>>>
逻辑右移772.5对象的相等性二、操作符即方法自然相等性:字面上的值相等,就认为两个对象相等。引用相等性:构造的对象常常会赋给一个变量,即让变量引用该对象。引用相等性用于比较两个变量是否引用了同一个对象。用“==”和“!=”比较用“eq”和“ne”比较思考:两个变量引用了两个完全一样的对象,两种相等性分别是什么?自然相等性:true引用相等性:false78二、操作符即方法举例:2.5对象的相等性scala>vala=List(1,0,-1)
vala:List[Int]=List(1,0,-1)
scala>valb=List(1,0,-1)
valb:List[Int]=List(1,0,-1)
scala>valc=List(1,0,1)
valc:List[Int]=List(1,0,1)
scala>vald=a
vald:List[Int]=List(1,0,-1)scala>a==c
valres0:Boolean=false
scala>a==b
valres1:Boolean=true
scala>aeqb
valres3:Boolean=false
scala>aeqd
valres4:Boolean=true79二、操作符即方法2.6小结介绍了“操作符即方法”这个重要概念。熟悉了三种操作符的定义和使用学习了操作符的优先级和结合性两种对象相等性的判断80三、类继承813.1Scala的类继承三、类继承节省代码量的两种策略:包含和继承。包含:
“hasa”一个类包括了另一个类的实例823.1Scala的类继承三、类继承节省代码量的两种策略:包含和继承。继承:
“isa”从一个宽泛的类可以派生出更加具体的类生物植物动物狗猫鸭超类超类子类子类833.1Scala的类继承三、类继承从一个宽泛的类可以派生出更加具体的类class子类名
extends
超类名
{
类体
}继承的基本语法被继承的类称为“超类”,而派生出来的类称为“子类”。如果继承层次较深,最顶层的类通常也叫“基类”。超类的超类也叫超类,子类的子类还叫子类。子类可以继承超类的字段和方法。843.1Scala的类继承三、类继承class子类名
extends
超类名
{
类体
}scala>classA{
|vala="ClassA"
|}
classA
scala>classBextendsA{
|valb="ClassBinheritsfromA"
|}
classB
scala>valx=newB
x:B=B@1919e19
scala>x.a
res0:String=ClassA
scala>x.b
res1:String=ClassBinheritsfromA定义子类B继承自超类A853.2调用超类的构造方法三、类继承子类调用超类的构造方法的语法class子类(子类对外接收的参数)extends
超类(子类给超类的参数)在构造某个类的对象时,如果这个类继承自另外一个类,那么应该先构造超类对象的组件,再来构造子类的其他组件。超类构造方法继承的构造方法调用顺序:子类构造方法863.2调用超类的构造方法三、类继承超类构造方法继承的构造方法调用顺序:子类构造方法scala>classA(vala:Int)
classA
scala>classB(giveA:Int,valb:Int)extendsA(giveA)
classB
scala>valx=newB(10,20)
x:B=B@14e554f
scala>x.a
res0:Int=10
scala>x.b
res1:Int=20class子类(子类对外接收的参数)extends
超类(子类给超类的参数)873.3重写超类的成员三、类继承金属超类中的某个属性可能并不一定符合子类的情况,子类需要一个新的符合子类行为的版本。固态液态重写override成员定义
重写超类的成员的语法防止意外的重写改善了“脆弱基类”的问题883.3重写超类的成员三、类继承不可重写的成员无参方法与字段final超类成员子类不可重写final类类不可被继承Scala在调用无参方法和调用同名的字段时形式相同无参方法字段重写不能重写方法的返回类型必须和字段的类型一致!893.3重写超类的成员三、类继承无参方法字段重写不能重写scala>classA{
|defjustA()="A"
|}
classA
scala>classBextendsA{
|overridevaljustA="B"
|}scala>classD{
|vald=10
|}
classD
scala>classEextendsD{
|overridedefd()=100
|}将无参方法重写为字段将字段重写为无参方法×√903.4子类型多态与动态绑定三、类继承子类型多态:类型为超类的变量可以指向子类的对象。对于方法:尽管变量的类型是超类,方法的版本却是“动态绑定”的。调用的方法要运行哪个版本,是由变量指向的对象来决定的scala>classA{
|defdisplay()="I'mA."
|}
classA
scala>classBextendsA{
|overridedefdisplay()="I'mB."
|}
classB
scala>valx:A=newB
valx:A=B@6ebece
scala>x.display()
valres0:String=I'mB.变量x的类型为超类A,但指向的对象为子类B的对象913.5抽象类三、类继承如果类里包含了没有具体定义的成员——没有初始化的字段或没有函数体的方法,那么这个类就是抽象类,必须用关键字“abstract”修饰。存在抽象成员:不能构造出具体的对象,不能用“new”初始化!(抽象类)超类成员:抽象子类成员:具体子类实现超类的抽象成员子类实现超类的抽象成员时,关键字“override”可写可不写。923.5抽象类三、类继承objectAbstractClass{
defmain(args:Array[String]):Unit={
//valx=newJ//抽象类不能通过“new”来构造实例对象
//error:classJisabstract;cannotbeinstantiated
valy=newK(1)
//构造子类的对象
println(y.j)//访问被子类“实现”了超类的抽象成员j
println(y.k)//输出:1
}
}
abstractclassJ{//定义抽象类J
valj:Int//声明了抽象成员,没有”定义“
}
classK(valk:Int)extendsJ{//定义子类K
valj=k*2//子类“实现”了超类的抽象成员j
}933.6Scala类的层次结构三、类继承/tour/unified-types.html抽象类,是所有类的超类值类引用类自定义的类Null:空引用,即指向JVM里的空内存Nothing:所有值类和引用类的子类,甚至还是Null类的子类。不仅表示空引用,还表示空值943.6Scala类的层次结构三、类继承/tour/unified-types.html值类的隐式转换scala>valx:Long=987654321
x:Long=987654321
scala>valy:Float=x
y:Float=9.8765434E8
scala>valz:Long=y
<console>:12:error:typemismatch;用于对象在两个类之间进行类型转换95三、类继承3.7小结类继承的概念和方法子类调用超类的构造方法重写超类的成员子类型多态与动态绑定抽象类Scala类的层次结构在编写Chisel时,类继承主要用于编写接口,使接口可以扩展!96四、特质974.1什么是特质四、特质特质天生就是抽象的,可以包含抽象成员;但是不需要用“abstract”修饰,也不能用“new”来实例化。特质内部可以包含字段和方法,甚至包含其他单例对象、类和特质的定义。单例对象、类、和特质都可以混入特质,也可以用“override”来重写特质成员。Scala只允许继承自一个类,但是对特质的混入数量却没有限制。98scala>classA{
|vala="ClassA"
|}
definedclassA
scala>traitB{
|valb="TraitB"
|}
definedtraitB
scala>objectCextendsAwithB
definedobjectC
scala>C.a
res1:String=ClassA
scala>C.b
res2:String=TraitB
4.1什么是特质四、特质单例对象、类以及特质在混入一个特质后,就包含了特质的所有公有成员。代码举例:可以用关键字“extends”继承类或混入特质;当混入多个特质时,后续关键字使用“with”。特质的定义使用关键字“trait”,且不能有入参。994.2特质的层次四、特质特质也可以继承自其他类,或混入任意个特质。在特质没有继承和混入时,那么这个特质就是AnyRef类的子特质。当某个类、单例对象或特质用关键字“extends”混入一个特质时,会隐式继承自这个特质的超类。特质对混入有一个限制条件:类、单例对象和特质混入特质时,它们的超类必须是待混入特质的超类,或者是待混入特质的超类的子类。100scala>classA
scala>classBextendsA
scala>classC
scala>traitDextendsA
scala>traitEextendsB
scala>classTest1extendsAwithD
definedclassTest1
scala>classTest2extendsBwithD
definedclassTest24.2特质的层次四、特质代码举例:特质D继承自类A特质E继承自类B类Test1的超类是类A特质D的超类也是类A类Test2的超类是类B,也就是A的子类特质D的超类也是类A101scala>classA
scala>classBextendsA
scala>classC
scala>traitDextendsA
scala>traitEextendsB
scala>classTest3extendsCwithD
<console>:13:error:illegalinheritance;superclassCisnota
subclassofthesuperclassAofthemixintraitD
classTest3extendsCwithD
^4.2特质的层次四、特质代码举例:类Test3的超类是类C特质D的超类的类A1024.3混入特质的简便方法四、特质还可以在最前面加上一个想要继承的超类:newTrait1withTrait2...{definition}newSuperClasswithTrait1withTrait2...{definition}实际上,此处定义了一个匿名类等效代码:classAnonymousClassextendsTrait1withTrait2...{definition}
newAnonymousClass1034.3混入特质的简便方法四、特质代码举例:scala>traitA{
|vala="IcomefromtraitA!"
|}
definedtraitA
scala>traitB{
|valb="IcomefromtraitB!"
|}
definedtraitB
scala>valC=newAwithB
C:AwithB=$anon$1@5a058be5
scala>C.a
res0:String=IcomefromtraitA!
scala>C.b
res1:String=IcomefromtraitB!1044.4特质的线性化叠加计算四、特质需要在特质里定义同名同参的方法,并用关键字组合“abstractoverride”修饰。特质对该方法的定义必须出现“super.方法名(参数)”。abstractclassA{defm(s:String):String}
classXextendsA{defm(s:String)="X->"+s}
traitBextendsA{abstractoverridedefm(s:String)=super.m("B->"+s)}
traitCextendsA{abstractoverridedefm(s:String)=super.m("C->"+s)}
traitDextendsA{abstractoverridedefm(s:String)=super.m("D->"+s)}
traitEextendsC{abstractoverridedefm(s:String)=super.m("E->"+s)}
traitFextendsC{abstractoverridedefm(s:String)=super.m("F->"+s)}
classGextendsX{overridedefm(s:String)="G->"+s}
valx=newGwithDwithEwithFwithB
println(x.m("End"))//G->D->C->E->F->B->End1054.4特质的线性化叠加计算四
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 临床护理管理与团队协作技巧
- 2026年河北美术学院高职单招职业适应性考试参考题库带答案解析
- 2026年安徽冶金科技职业学院高职单招职业适应性考试备考题库带答案解析
- 2026年芜湖职业技术学院单招综合素质笔试模拟试题附答案详解
- 肿瘤护理护理实践研究
- 2026年广东生态工程职业学院单招综合素质考试模拟试题带答案解析
- 医院临床护理技能培训礼仪
- 手术麻醉技术更新与挑战
- 儿科急症处理与急救技巧
- 2026年杭州万向职业技术学院单招综合素质考试模拟试题带答案解析
- 2025年广东省深圳市中考英语复习听说题型课件信息复述提问
- 咖啡消费人群的细分与定位-全面剖析
- 09.品质月报统计表模板
- 游戏推广合作协议书范本
- 2024-2025学年北京朝阳区九年级初三(上)期末历史试卷(含答案)
- 2025版国家开放大学法学本科《知识产权法》期末纸质考试总题库
- DB11T 354-2023 生活垃圾收集运输管理规范
- 赤石特大桥施工安全风险评估报告
- QBT 2770-2006 羽毛球拍行业标准
- 售后服务流程管理手册
- 2020-2021学年新概念英语第二册-Lesson14-同步习题(含答案)
评论
0/150
提交评论