Scala01入门

1章 可伸展的语言

Scala应用范围广,从编写脚本,到建立大型系统。

运行在标准Java平台上,与Java库无缝交互。

更能发挥力量的地方:建立大型系统或可重用控件的架构。

将面向对象和函数式编程加入到静态类型语言。


Scala中,函数就是对象。函数类型是能够被子类继承的类。

Scala是纯粹的面向对象语言:每个值都是对象,每个操作都是方法调用。如1+1,实际是调用Int里的+方法。

 

语言分类:

指令式语言 imperative

函数式语言 functional


函数式编程:

函数是对能产生值的表达式的定义。

两种指导理念:

1、函数是头等值。

函数也是,与整数、字符串处于同一个地位;

可以当作参数传递给其他函数;

可以当作结果从函数中返回或保存在变量里;

可以在函数里定义其他函数,就好像在函数里定义整数一样;

可以定义匿名函数,并随意插入到代码的任何地方。

2、程序的操作应该把输入值映射为输出值而不是就地修改数据。

不可变数据结构是函数式语言的一块基石;

Scala中的不可变列表元组、映射表、集;

无副作用

 

Scala的兼容性:

Scala程序被编译成JVM字节码,性能与Java相当。

自由调用Java类库。

允许定义类型失配或者选用不存在的方法时使用隐式类型转换(implicit conversion)。

 

Scala定义类: 

class MyClass(index:Int, name:String)
含有两个私有字段,以及一个构造函数。


测试只能证明错误存在,而非不存在。

有用的文档是那些程序的读者自己不可能很容易的看懂程序功能的文档。

 

类型推断 type inference

 


第2章 Scala入门初探第2章 Scala入门初探

Scala解释器:

resX 解释器自动产生的计算结果

val 只能赋值一次

var 可以赋值多次

 

两次回车键取消多行输入

 

函数定义:

def max(x:Int, y:Int):Int={function block;
}


参数类型必须指定。

函数结果(result type)类型  如果递归定义则必须指定,否则可以不用显示指定而用类型推断。

 

如果函数只有一行表达式,可省略{}

当函数没有返回值时返回Unit

结果类型为Unit的函数是为了其运行效果,即side effect

 

脚本:经常会被执行的,放在文件中的子序列。

> scala hello.scala arguments

脚本中访问脚本参数:args(0)

args.foreach(arg=>println(arg))
args.foreach(println)


函数字面量语法结构:括号、命名参数列表、右箭头、函数体

(x:Int, y:Int) => x+y

for(arg <- args)println(arg)


3Scala入门再探

3.1 类型参数化数组

val greetStrings=new Array[String](3)
greetStrings(0)="Hello"
greetStrings(1)=", "
greetStrings(2)="world!\n"val greetStrings = Array("Hello",", ","world!\n")
for(i<-0 to 2)print(greetString(i))

1、[String]新建一个String型的数组;

2、数组用(index)引用其中的值;

3、若方法只有一个参数,调用时可以省略点及括号;

(0).to(2)  0 to 2       println(10)  Console println 10

4Scala没有传统意义上的操作符,取而代之的是+-*/这样的字符作为方法名,1+2 是方法的调用:(1).+(2)

 

用括号访问数组:数组也是对象,实质为对象的值参数,调用的是apply方法

用括号传递给变量一个或多个值参数时,scala会把它转换成对apply方法的调用。

任何对于对象的值参数应用都被转换为对apply方法的调用。前提是这个类型定义了apply方法。

arrayObject(i)被转换为arrayObject.apply(i)

 

当对带有括号并包括一到若干参数的变量赋值时,编译器将使用对象的update方法对括号里的参数和等号右边的对象执行调用。

greetStrings(0)=”Hello”

greetStrings.update(0,”Hello”)

 

val numNames = Array(“zero”,”one”,”two”)

val numNames = Array.apply(“zero”,”one”,”two”)

调用apply工厂方法,可以有不定个数的参数,定义在Array的伴生对象(companion object)中。

 

3.2 使用列表(list)

方法没有副作用是函数式编程的重要概念,计算并返回值应该是方法的唯一目的。

数组是可变的同类对象序列。

列表是不可变的同类对象序列,为的是方便函数式编程。


val oneTwo=List(1,2)
val threeFour=List(3,4)
val all=oneTwo::threeFour
val all=1::2::3::4::Nil

:::列表叠加,新建列表并返回

::前插    Nil是空列表    带冒号的方法调用者是后者,1::Nil   Nil.::(1)

如何append

1、::前插,再reverse;

2、ListBuffer支持append,toList

 

3.3 使用元组(Tuple)

不可变,可包含不同类型的元素。

如果在方法里返回多个对象,java的做法是创建JavaBean以包含多个返回值,Scala里可以返回元组来达到目的。

val pair=(99,"Luftballons")
println(pair._1+" "+pair._2)
用点号、下划线和基于1 的索引访问其中的元素。

列表的apply方法始终返回同样的类型,所以可以用(index)访问,而元组中元素的类型都不同,所以用._index访问。

1开始是依传统设定的。

 

3.4 使用集(set)和映射(map)

scala.collection.immutable.Set

scala.collection.mutable.Set

scala.collection.imutable.HashMap

scala.collection.mutable.HashMap

默认为immutable

 

3.5 学习识别函数式风格

如果包含var变量,可能是指令式风格;

如果仅含val变量,可能是函数式风格。

 

指令式风格

def printArgs(args :Array[String]):Unit={var i = 0while(i<args.length){println(args(i))i+=1}
}

函数式风格

def printArgs(args:Array[String]):Unit={for(arg<-args)println(args) //args.foreach(println)

每个有用的程序都会有某种形式的副作用,否则就不可能向程序之外提供什么有价值的东西。

 

无副作用的代码使测试变得容易:

def formatArgs(args:Array[String])=args.mkString("\n")
val res=formatArgs(Array("zero","one","two"))
assert(res=="zero\none\ntwo")

Scalaassert方法检查传入的Boolean表达式,如果为假,抛出AssertionError

 

Scala程序员的平衡感:

崇尚val、不可变对象、无副作用的方法;

只有在特定需要和加以权衡之后才选择var、可变对象、有副作用的方法。

 

3.6 从文件里读取文本行(脚本)

import scala.io.Source
def widthOfLength(s:String)=s.length.toString.length
if(args.length>0){val lines=Source.fromFile(args(0)).getLines.toListval longestLine=lines.reduceLeft((a,b)=>if(a.length>b.length)a else b)val maxWidth=widthOfLength(longestLine)for(line<-lines){val numSpaces=maxWidth-widthOfLength(line)val padding=" "*numSpacesprint(padding+ling.length+"|"+line)
}
elseConsole.err.println("Please enter filename")


Source.fromFile(args(0)).getLines方法返回一个迭代器Iterator[String]

getLines方法返回的是迭代器,一旦遍历完成就失效了,所以要toList


4章 类和对象

4.1 类、字段、方法

成员(member:

valvar定义字段

def定义方法

 

字段的另一种说法:实例变量(instance variable

 

私有字段只能被同一个类里的方法访问,所有能更新字段的代码都被锁定在类里。

声明字段私有:private关键字

PublicScala的默认访问级别。

class ChecksumAccumulator{private var sum=0def add(b:Byte):Unit=sum+=b //def add(b:Byte){sum+=b}def checksum():Int=~(sum&0xFF)+1
}


Scala方法参数都是val,即C++的常引用。

如果没有显式返回语句,Scala方法将返回方法中最后一次计算得到的值。

如果函数只有一行表达式,可省略{}

对结果类型为Unit的方法来说,执行的目的就是为了它的副作用——能够改变方法之外的某处状态或执行I/O活动

过程(procedure)——一种仅为了副作用而执行的方法。

定义函数时,没有等号,返回的是Unit  def add(b:Byte){sum+=b}

 

4.2 分号推断

语句末尾的分号通常可选,如果一行包含多条语句,必须加分号。

val s = “hello”; println(s)

除非以下情况之一成立,否则行尾被认为是一个分号。

1、疑问行由一个不能合法作为语句结尾的字结束,如句点或中缀操作符;

2、下一行开始于不能作为语句开始的词;

3、行结束于()[]内部,因为这些符号不能容纳多个语句。

 

4.3 Singleton对象

Scala不能定义静态成员,取而代之的是定义单例对象(singleton object

object关键字替换class关键字。

import scala.collection.mutable.Map
object ChecksumAccumulator{private val cache=Map[String,Int]()def calculate(s:String):Int=if(cache.contains(s))cache(s) //返回键s对应的值else{val acc=new ChecksumAccumulaterfor(c<-s)acc.add(c.toByte)val cs=acc.checksum()cache+=(s->cs)cs}
}

单例对象,对应于java的静态方法工具类。

当单例对象与某个类共享同一个名称时,被称为这个类的伴生对象(companion object)。

同名类的伴生对象,与伴生类(companion class)在一个源文件中。

类和其伴生对象可以互相访问其私有成员。

 

单例对象名.方法名  CheckSumAccumulator.calculate(“Every value is an object”)

单例对象不是类型,它扩展了伴生类的父类并可以混入特质。

可以使用类型调用单例对象,或者类型的实例变量指代单例对象,并把它传递给需要类型参数的方法。

单例对象不带参数,而类可以。因为单例对象不是new实例化的,没机会传递给它实例化参数。

每个单例对象都被实现为虚构类(synthetic class)的实例,并指向静态的变量。

虚构类的名称是对象名后加一个美元符,单例对象ChecksumAccumulator的虚构类是ChecksumAccumulator$

单例对象在第一次访问时被初始化。

 

没有伴生类的单例对象被称为独立对象(standalone object,可用于相关功能方法的工具类,或者定义Scala应用的入口点。

 

4.4 Scala程序

能独立运行的Scala程序,必须创建main方法的单例对象——仅一个参数Array[String],且结果类型为Unit

 

以定义结尾的都不是脚本。

脚本:以结果表达式结束。

 

$ scalac ChecksumAccumulator.scala Summer.scala  或者

快速Scala编译器,fast Scala compiler,将编译程序加载入后台

$ fsc ChecksumAccumulator.scala Summer.scala

$ fsc -shutdown

 

import ChechsumAcculator.calculate
object Summer{def main(args:Array[String]){for(arg<-grgs)println(arg+":"+calculate(arg))}
}

Scala源文件默认引用java.langscala、单例对象Predef

println语句即为Predef单例对象的printlnPredef.println转而调用Console.println)。

assert实际调用Predef.assert

 

4.5 Application特质

import ChecksumAcculator.calculate
object FallWinterSpringSummer extends Application{for(season<-List("fall","winter","spring","summer"))println(season+":"+calculate(season))
}

特质Application声明了带有合适签名的main方法,并被单例对象继承。

大括号之间的代码被收集进了单例对象的主构造器(primary constructor),并在类初始化时执行。

Scala提供scala.Application特质,可以减少输入工作。

但无法访问命令行参数,无法应用于多线程。

 

数组Array 可变同类对象序列

列表List 不可变同类对象序列

元组Tuple 不可变非同类对象序列

集合Set  映射Map 有可变和不可变

 

5章 基本类型和操作

5.1 基本类型和操作

整数类型 integral type

Byte

Short

Int

Long

Char

数类型 numeric type

Float

Double

 

String  属于java.lang

Boolean

 

5.2 字面量

字面量literal——直接写在代码里的常量值。

 

原始字符串raw string 三个双引号对之间的字符串,字符串中可以包含任意字符,不用转义。

 “””|line1

    |line2”””.stripMargin 此方法使结果符合预期

 

符号字面量——除了显示名字,什么都不能做。

符号字面量被写成’<标识符>

被映射成预定义类scala.Symbol的实例,即被编译器扩展为工厂方法调用:Symbol(“标识符”)

应用场景:动态类型语言中使用一个标识符。

>val s = ‘aSymbol

>s.name  #aSymbol

如果同一个符号字面量出现两次,那么两个字面量指向的是同一个Symbol对象。

 

5.3 操作符和方法

操作符实际只是普通方法调用的另一种表现形式。

值类型对象调用方法的简写形式。

任何方法都可以被当做操作符来标注。

>val s=”hello, world”

>s.indexof(‘o’)

>s indexof ‘o’

中缀标注

前缀标注  -2.0 实际为 (2.0).unary_-    + - ! ~四种操作符可被用作前缀标注

后缀标注  s toLowerCase  不用点号或括号调用不带任何参数的方法

 

中缀是二元的,前缀和后缀是一元的。

 

Scala中,方法调用的空括号,有副作用就加上,没副作用就省略。

 

5.7 对象的相等性

首先检查左侧是否为null,如果不是,调用左操作数的equals方法。

精确比较取决于左操作数的equals方法定义。

Java中的==对基本类型,比较的是值相等性;对于引用类型,比较的是引用相等性,即是否指向JVM堆里的同一个对象。

5.8 操作符的关联性

任何以:字符结尾的方法,右操作数调用方法,传入左操作数 a:::b   b.:::(a)

其余相反。

 

5.9 富包装器

Scala基本类型的方法很多。


Scala基本类型都隐式转换(implicit conversion)为富包装器类型,可对外提供多种额外的方法。

想要看到基本类型的所有可用方法,可以查看基本类型的富包装器的API文档。

 

第6章 函数式对象

本章重点:函数式对象——不具有任何可改变状态的对象的类。

不可变对象的优点:

1、对象状态不可变,思路清晰;

2、无线程安全问题;

3、让哈希键值更安全。

缺点:需要赋值很大的对象表,可变对象可以原址更新。

6.1 Rational的规格说明书

有理数:rational number  状态不可变,两个有理数运算后将产生新的有理数。

分子:numerator

分母:denominator

约分:normalized

 

6.2 创建Rational

class Rational(n:Int,d:Int)

如果类没有主体,不需要花括号。

n,d称为类参数class parameter)。

Scala编译器会收集这两个类参数并创造出一个主构造器primary constructor)。

类内部任何既不是字段又不是方法的代码将被编译进主构造器中,每次新建实例时执行。

class Rational(n:Int,d:Int){println("Create"+n+"/"+d)
}


6.3 重新实现toString方法

类默认继承了java.lang.Object类的toString实现,打印  类名@地址。

重写(override)toString方法:

class Rational(n:Int,d:Int){override def toStirng=n+"/"+d
}

 

6.4 检查先决条件

分子不能为零

先决条件是对传递给方法或构造器的值的限制,是调用者必须满足的需求。

为主构造器定义先决条件(precondition:

使用require方法:(定义在scala包的独立对象Predef上)

class Rational(n:Int,d:Int){require(d!=0)override def toStirng=n+"/"+d
}

Require方法带一个boolean参数,如果为真,正常返回;反之,require将抛出IllegalArgumentException阻止对象被构造。

 

6.5 添加字段

类参数是为了给字段赋值,所以要添加字段。

class Rational(n:Int,d:Int){required(d!=0)val numer:Int=nval denom:Int=doverride toString=numer+"/"+denomdef add(that:Rational):Rational=new Rational(numer*that.denom+that.num*denom,denom*that.denom)
}

添加了两个字段,并用参数初始化他们。

 

6.6 自指向

关键字this指向当前执行方法被调用的对象实例。

def lessThan(that:Rational)=this.numer*that.denom<that.num*this.denom

6.7 辅助构造器Auxiliary constructor

辅助构造器都是以this(...)形式开头。

每个辅助构造器的第一个动作都是调用同类的别的构造器。

被调用的构造器可以是主构造器,也可以是别的辅助构造器。

每个Scala构造器最终调用主构造器。主构造器是类的唯一入口点。

 

6.8 私有字段和方法


最大公约数:greatest common divisor

初始化器:initializer——对字段进行初始化的代码n/g  d/g

 

6.9 定义操作符

直接将add替换为+

 

 

6.10 Scala的标识符

1、字母数字式 alphanumeric identifier  

字母、下划线开头,之后跟字母数字下划线。

$为编译系统所用的标识符,用户程序不应包含。不建议用“_”结尾

驼峰式camel case:类和特质开头大写,其余开头小写。

Java中常量名大写且用“_”分隔,Scala中的常量也用驼峰式。

2、操作符 operator identifier

Scala编译器将操作符标识符转换成合法的内嵌”$”java标识符。

:->将被内部表达为$colon$minus$greater

3、混合标识符 mixed identifier

由字母数字组成,后面跟着下划线和一个操作标识符。

unary_+ 前缀

myvar_=被用作定义赋值操作符的方法名,是由编译器产生的用来支持属性(property)的。

4、字面量标识符 literal identifier

用反引号包括的任意字符串`...`

可以把运行时环境认可的任意字符串放在反引号之间当作标识符,结果总被当作是Scala标识符。即使反引号中的是保留字也有效。

javaThread类中访问静态的yield方法是典型应用:

因为yieldScala的保留字,所以不能写成Thread.yield(),可以写成Thread.`yield`()

 

6.11 方法重载 overload


 

6.12 隐式转换

类似于C++的转换构造函数。实际定义在伴生对象中。

implicit def intToRational(x:Int)=new Rational(x)

此时,可执行操作:

>val r=new Rational(2,3)

>2*r  //2转换为Rational

注意:要隐式转换起作用,需要将隐式转换函数定义在作用范围之内。

隐式转换函数是隐式调用。

编程时要在简洁性和可读性之间进行权衡。




 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387199.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java网络01基本网络概念

协议 Protocol&#xff1a;明确规则 &#xff08;1&#xff09;地址格式&#xff1b; &#xff08;2&#xff09;数据如何分包&#xff1b; ... TCP/IP四层模型&#xff1a; 应用层 HTTP SMTP POP IMAP 传输层 TCP UDP 网际层 IP 主机网络层 host to host layer 数模、…

Java网络02基本Web概念

URI Uniform Resource Identifier 同一资源标识符 以特定语法标识一个资源的字符串 绝对URI&#xff1a;URI模式模式特有部分 scheme:scheme-specific-part scheme分为&#xff1a; data file本地文件系统 ftp http telnet urn 统一资源名 scheme-specific-part为&am…

解决自建ca认证后浏览器警告

前一篇讲解了基本的建立证书的过程&#xff0c;但是建立后总是会在浏览器那里警告&#xff1a; 此链接不是私密链接 --谷歌浏览器 此证书颁发机构不可信 此证书不是这个网站的 --ie浏览器 总之证书是生成成功了&#xff0c;但是其中的内容填写错误了&a…

Java网络03流

网络程序所做的很大一部分工作只是输入和输出&#xff1a;从一个系统向另一个系统移动数据。 输出流 Java的基本输出流类是java.io.OutputStream: public abstract class OutputStream 这个类提供了写入数据所需的基本方法&#xff0c;包括&#xff1a; public abstract vo…

基于微信小程序开发的仿微信demo

(本文参考自github/liujians,地址:https://github.com/liujians/weApp) 作者声明&#xff1a; 基于微信小程序开发的仿微信demo 整合了ionic的样式库和weui的样式库 使用请查看使用必读! 更新日志请点击这里 目前功能 查看消息 网络请求获取数据&#xff08;download示例server…

解决idea 中web项目无法正常显示的问题

转载于:https://www.cnblogs.com/nulijiushimeili/p/10575364.html

分享一个前后端分离的web项目(vue+spring boot)

Github地址&#xff1a;https://github.com/smallsnail-wh 前端项目名为wh-web后端项目名为wh-server项目展示地址为我的github pages&#xff08;https://smallsnail-wh.github.io&#xff09;用户名&#xff1a;admin&#xff0c;密码admin&#xff08;第一次启动会比较慢&am…

部署php项目到linux

服务器&#xff1a;39.106.26.67rootBayou2009 数据库&#xff1a;rootbayou2009 项目文件夹路径&#xff1a;/home/www/项目文件夹名称&#xff1a;education.bayou-tech.cn 绑定域名&#xff1a;education.bayou-tech.cn 绑定域名&#xff1a; 用ftp把配置文件下班到windows修…

ZooKeeper安装配置

配置 1、在conf目录下创建一个配置文件zoo.cfg tickTime2000 dataDir.../zookeeper/data dataLogDir.../zookeeper/dataLog clientPort2181 initLimit5 syncLimit2 server.1server1:2888:3888 server.2server2:2888:3888 server.3server3:2888:3888 •tickTime&#…

ionic2开发的仿外卖点餐系统(Ionic2+Angular2

github上的项目源码 Run this Project&#xff08;运行该项目&#xff09; first&#xff08;首先&#xff09;: make sure your computer install ionic 确保你的电脑安装了ionic2,不懂自行百度 second&#xff08;其次&#xff09;:$ ionic start wechat_restaurant tutorial…

node搭建服务器,写接口,调接口,跨域

刚开始学node&#xff0c;今天做这个也是累死宝宝了&#xff0c;以后可以自己写接口自己用了&#xff0c;再也不用麻烦人家后台人员了&#xff0c;这些年我们欠他们的太多了&#xff0c;说多了都是泪&#xff0c;不多说&#xff0c;往下看吧。。。 服务端项目目录下&#xff1a…

ThreadPoolExcutor 线程池 异常处理 (上篇)

前言 最近看到crossoverJie的一篇文章&#xff1a;一个线程罢工的诡异事件 首先感谢原作者的分享&#xff0c;自己获益匪浅。然后是回想到自己的一次面试经历&#xff0c;面试官提问了线程池中的线程出现了异常该怎样捕获&#xff1f;会导致什么样的问题&#xff1f; 示例代码 …

ionic3 调用本地相册并上传图片

前言在APP中启动相册选择器或者拍照上传图片这些功能是非常常见的。对于Ionic2&#xff0c;我们只能通过cordova插件实现调用原生的功能。下面将简单的封装一个选择相册或拍照上传图片的ImgService服务。具体如下。 Cordova准备下载安装所需的Cordovar插件&#xff1a; Image P…

Mapreduce中maptask过程详解

一、Maptask并行度与决定机制 1.一个job任务的map阶段的并行度默认是由该任务的大小决定的&#xff1b; 2.一个split切分分配一个maprask来并行处理&#xff1b; 3.默认情况下&#xff0c;split切分的大小等于blocksize大小&#xff1b; 4.切片不是mapper类中对单词的切片&…

angularjs 上传

xxx.module.ts模块 import { NgModule} from “angular/core”; import { FileUploadModule } from “ng2-file-upload” ; import { XXXComponent } from “./xxx.component”; NgModule({ imports:[ FileUploadModule ], declarations:[ XXXComponent &#xff0c;/component…

PHPCMS的产品筛选功能

如下图所示功能&#xff1a; 首先&#xff0c;用下面这些代码替换掉phpcms/libs/functions/extention.func.php的内容 <?php /*** extention.func.php 用户自定义函数库** copyright (C) 2005-2010 PHPCMS* license http://www.phpcms.cn/licen…

程序员自身价值值这么多钱么?

xx 网络公司人均奖金 28 个月…… xx 科技公司人均奖金 35 个月…… 每到年底&#xff0c;这样的新闻在互联网业内简直是铺天盖地。那些奖金不高的程序员们一边羡慕嫉妒&#xff0c;一边暗暗比较一下自己的身价&#xff0c;考虑是不是该跳槽了。 不同水平的程序员&#xff0c;薪…

Spring MVC中使用 Swagger2 构建Restful API

0.Spring MVC配置文件中的配置[java] view plaincopy<!-- 设置使用注解的类所在的jar包&#xff0c;只加载controller类 --> <span style"white-space:pre"> </span><context:component-scan base-package"com.jay.plat.config.contro…

platform(win32) 错误

运行cnpm install后&#xff0c;出现虽然提示不适合Windows&#xff0c;但是问题好像是sass loader出问题的。所以只要执行下面命令即可&#xff1b;方案一&#xff1a;cnpm rebuild node-sass #不放心可以重新安装下 cnpm install方案二&#xff1a;npm update npm install no…

Error: Program type already present: okhttp3.Authenticator$1

在app中的build.gradle中加入如下代码&#xff0c; configurations {all*.exclude group: com.google.code.gsonall*.exclude group: com.squareup.okhttp3all*.exclude group: com.squareup.okioall*.exclude group: com.android.support,module:support-v13 } 如图 转载于:ht…