Scala教程 逐步学习Scala的指南
Scala是一种通用的、高级的、多范式的编程语言。它是一种纯粹的面向对象的编程语言,同时也为函数式编程方法提供支持。Scala程序可以转换为字节码,可以在JVM(Java虚拟机)上运行。Scala代表可扩展的语言。Scala不提供任何对.Net框架的支持。Scala是由Martin Odersky设计的,他是瑞士洛桑联邦理工学院(EPFL)的编程方法教授,也是一位德国计算机科学家。Scala于2004年首次在Java平台上公开发布,是其第一个版本。在2004年6月。scala的最新版本是2.12.6,于2018年4月27日发布。
主题:
Scala的特点
Scala的流行和需求有很多原因。以下是其中的几个原因:
- 面向对象: Scala中的每个值都是一个对象,所以它是一种纯粹的面向对象的编程语言。对象的行为和类型是由Scala中的类和特征来描述的。
- 功能性: 它也是一种功能性编程语言,因为每个函数都是一个值,每个值都是一个对象。它提供了对高阶函数、嵌套函数、匿名函数等的支持。
- 静态类型化: 在Scala中,验证和执行类型约束的过程是在编译时完成的。与其他静态类型的编程语言如C++、C等不同,Scala不期望用户提供多余的类型信息。在大多数情况下,用户不需要指定类型。
- 可扩展性: 新的语言结构可以以库的形式添加到Scala中。Scala被设计为与JRE(Java Runtime Environment)互为补充。
- 并发和同步处理: Scala允许用户以不可改变的方式编写代码,这使得应用并行(同步)和并发变得容易。
应用程序领域
开始使用Scala
Scala是一种兼容性很强的语言,因此可以非常容易地安装到Windows和Unix操作系统中。
,因为Scala在语法上与其他广泛使用的语言有很多相似之处,所以用Scala编码和学习比较容易。Scala程序可以在任何纯文本编辑器上编写,如记事本、记事本++,或任何类似的东西。人们也可以使用在线IDE来编写Scala代码,甚至可以在自己的系统上安装一个IDE,使编写这些代码更加可行,因为IDE提供了很多功能,如直观的代码编辑器、调试器、编译器等。
要开始编写Scala代码并执行各种有趣和有用的操作,人们必须在自己的系统上安装scala。这可以按照下面提供的步骤来完成:
- 验证Java包
我们首先需要在计算机上安装一个Java软件开发工具包(SDK)。我们需要验证这个SDK包,如果没有安装,就安装它们。 - 现在安装Scala
我们已经完成了java的安装,现在我们来安装Scala包。下载这些软件包的最佳选择是只从官方网站下载:https://www.scala-lang.org/download/ 上面链接中的软件包大约有100MB的存储空间。下载完毕后,打开下载的.msi文件。 - 测试和运行Scala命令
现在打开命令提示符,输入以下代码。
C:\Users\Your_PC_username>scala
- 我们将收到如下所示的输出:
- 命令的输出。
如何运行一个Scala程序?
让我们考虑一个简单的Hello World程序。
// Scala program to print Hello World
// Creating object
object Geeks {
// Main method
def main(args: Array[String])
{
// prints Hello, Geeks!
println("Hello, World!")
}
}
输出:
Hello, World!
一般来说,有两种方式来运行Scala程序–
- 使用 在线IDE : 我们可以使用各种在线IDE,无需安装即可运行Scala程序。
- 使用命令行: 我们也可以使用命令行选项来运行Scala程序。以下步骤演示了如何在Windows/Unix操作系统中通过命令行运行Scala程序:
打开命令行,然后输入 scala Hello.scala 来编译代码 。 如果你的代码没有错误,那么它将正常执行并显示输出。
Scala的基本原理
变量
变量是一个简单的存储位置。每个变量都有自己的名字,并存储一些已知和未知的信息,称为值。在Scala中,有两种类型的变量:
- Mutable Variables: 这些变量是那些允许我们在声明变量后改变数值的变量。可变变量是通过使用 “var “关键字来定义的。
- 不可变的变量: 这些变量是那些不允许你在声明变量后改变数值的变量。不可变的变量是通过使用 “val “关键字定义的。
例如:
// Mutable Variable
var name: String = "geekforgeeks";
// Immutable Variable
val name: String = "geekforgeeks";
操作符
操作符是一个符号,代表对一个或多个操作数进行的操作。操作符允许我们对操作数进行不同类型的操作。Scala中使用的不同类型的操作符如下:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 赋值运算符
- 位操作符
示例:
// Scala program to demonstrate
// the Operators
// Creating object
object Geeks
{
// Main method
def main(args: Array[String])
{
// Operands
var a = 10;
var b = 4;
var c = true;
var d = false;
var result = 0;
// using arithmetic operators
println ("Addition is: "+ (a + b) );
println ("Subtraction is: "+ (a - b) ) ;
// using Relational Operators
if (a == b)
{
println ("Equal To Operator is True");
}
else
{
println ("Equal To Operator is False");
}
// using Logical Operator 'OR'
println("Logical Or of a || b = " + (c || d));
// using Bitwise AND Operator
result = a & b;
println ("Bitwise AND: " + result );
// using Assignment Operators
println ("Addition Assignment Operator: " + (a += b) );
}
}
输出
Addition is: 14
Subtraction is: 6
Equal To Operator is False
Logical Or of a || b = true
Bitwise AND: 0
Addition Assignment Operator: ()
决策
编程中的决策与现实生活中的决策类似。Scala使用控制语句来控制基于某些条件的程序执行流程。这些语句用于根据程序状态的变化,使执行流前进和分支。
Scala中的决策语句
- 如果
- If – else
- 嵌套 – if
- if – elsif 梯子
例1: 为了说明if和if-else的使用
// Scala program to illustrate the if and if-else statement
object Test
{
// Main Method
def main(args: Array[String])
{
// taking a variable
var a: Int = 650
// if condition to check
// for even number
if(a % 2 == 0)
{
println("Even Number")
}
if (a > 698)
{
// This statement will not
// execute as a > 698 is false
println("GeeksforGeeks")
}
else
{
// This statement will execute
println("Sudo Placement")
}
}
}
输出
Even Number
Sudo Placement
例2: 为了说明嵌套-if的使用
// Scala program to illustrate
// Nested if statement
object Test
{
// Main Method
def main(args: Array[String])
{
var a: Int = 10;
if(a % 2 == 0)
{
// Nested - if statement
// Will only be executed
// if above if statement
// is true
if(a % 5 == 0)
{
println("Number is divisible by 2 and 5\n")
}
}
}
}
输出
Number is divisible by 2 and 5
循环
程序设计语言中的循环是一种功能,它有助于在某些条件评估为真时重复执行一组指令/函数。循环使程序员的任务更加简单。Scala提供了不同类型的循环来处理程序中基于条件的情况。Scala中的循环有:
- for 循环
// Scala program to illustrate for loop
object forloopDemo {
// Main Method
def main(args: Array[String]) {
var y = 0;
// for loop execution with range
for(y <- 1 to 4)
{
println("Value of y is: " + y);
}
}
}
- 输出
Value of y is: 1
Value of y is: 2
Value of y is: 3
Value of y is: 4
- While循环
// Scala program to illustrate while loop
object whileLoopDemo
{
// Main method
def main(args: Array[String])
{
var x = 1;
// Exit when x becomes greater than 4
while (x <= 4)
{
println("Value of x: " + x);
// Increment the value of x for
// next iteration
x = x + 1;
}
}
}
- 输出
Value of x: 1
Value of x: 2
Value of x: 3
Value of x: 4
- Do-while 循环
// Scala program to illustrate do..while loop
object dowhileLoopDemo
{
// Main method
def main(args: Array[String])
{
var a = 10;
// using do..while loop
do
{
print(a + " ");
a = a - 1;
}while(a > 0);
}
}
输出
10 9 8 7 6 5 4 3 2 1
数组
数组是Scala中一种特殊的集合。它是一种固定大小的数据结构,存储相同数据类型的元素。它是一个可变值的集合。以下是其语法。
语法:
var arrayname = new Array[datatype](size)
它将创建一个包含40、55、63、17等数值的整数阵列。下面是访问数组中单个元素的语法,如果我们已经创建了一个名为 number 的数组,
number(0)
它将产生40的输出。
遍历一个数组
在这个例子中,我们创建一个数组,同时提供其元素的值。在这种情况下,类型是推断出来的。
// Scala program to accessing an array
// of the string as name.
object GFG
{
// Main method
def main(args: Array[String])
{
// allocating memory of 1D Array of string.
var name = Array("gfg", "geeks", "GeeksQuize",
"geeksforgeeks" )
println("second element of an array is: ")
// Accessing an array element
println(name(1) )
}
}
输出
second element of an array is:
geeks
字符串
字符串是一连串的字符。在Scala中,String的对象是不可改变的,也就是说,一旦创建,就是一个常量,不能改变。在Scala中,字符串类型是在满足字符串字面意义之前指定的。但当编译器满足字符串字面意义并创建一个字符串对象str时,
语法:
var str = "Hello! GFG"
or
val str = "Hello! GFG"
var str: String = "Hello! GFG"
or
val str: String = "Hello! GFG"
// Scala program to illustrate how to
// create a string
object Main
{
// str1 and str2 are two different strings
var str1 = "Hello! GFG"
val str2: String = "GeeksforGeeks"
def main(args: Array[String])
{
// Display both strings
println(str1);
println(str2);
}
}
输出
Hello! GFG
GeeksforGeeks
在Scala中串联字符串
当一个新的字符串通过添加两个字符串创建时,被称为字符串的连接。Scala提供了concat()方法来连接两个字符串,该方法返回一个用两个字符串创建的新字符串。你也可以使用’+’运算符来连接两个字符串。
// Scala program to illustrate how to
// concatenate strings
object Main
{
// str1 and str2 are two strings
var str1 = "Welcome! GeeksforGeeks "
var str2 = " to Portal"
// Main function
def main(args: Array[String])
{
// concatenate str1 and str2 strings
// using concat() function
var Newstr = str1.concat(str2);
// Display strings
println("String 1:" +str1);
println("String 2:" +str2);
println("New String :" +Newstr);
// Concatenate strings using '+' operator
println("This is the tutorial" +
" of Scala language" +
" on GFG portal");
}
}
输出
String 1:Welcome! GeeksforGeeks
String 2: to Portal
New String :Welcome! GeeksforGeeks to Portal
This is the tutorial of Scala language on GFG portal
函数
函数是执行某种任务的语句的集合。Scala被认为是一种函数式编程语言,因此这些函数发挥着重要作用。它使调试和修改代码更加容易。Scala函数是第一类值。以下是Scala函数的语法。
语法:
def function_name ([parameter_list]) : [return_type] = {
// function body
}
def 关键字用于在Scala中声明一个函数。
函数的调用: 在Scala中主要有两种方法来调用函数。第一种方式是标准方式,如下:
function_name(paramter_list)
在第二种方式中,用户也可以借助实例和点符号来调用函数,如下:
[instance].function_name(paramter_list)
// Scala program of function calling
object GeeksforGeeks {
def main(args: Array[String]) {
// Calling the function
println("Sum is: " + functionToAdd(5, 3));
}
// declaration and definition of function
def functionToAdd(a:Int, b:Int) : Int =
{
var sum:Int = 0
sum = a + b
// returning the value of sum
return sum
}
}
输出 :
Sum is: 8
Scala中的匿名函数 :
在Scala中,匿名函数也被称为函数字面。一个不包含名字的函数被称为匿名函数。
语法 :
(z:Int, y:Int)=> z*y
Or
(_:Int)*(_Int)
// Scala program to illustrate the anonymous method
object Main
{
def main(args: Array[String])
{
// Creating anonymous functions
// with multiple parameters Assign
// anonymous functions to variables
var myfc1 = (str1:String, str2:String) => str1 + str2
// An anonymous function is created
// using _ wildcard instead of
// variable name because str1 and
// str2 variable appear only once
var myfc2 = (_:String) + (_:String)
// Here, the variable invoke like a function call
println(myfc1("Geeks", "12Geeks"))
println(myfc2("Geeks", "forGeeks"))
}
}
输出 :
Geeks12Geeks
GeeksforGeeks
Scala嵌套函数:
在另一个函数内定义的函数被称为嵌套函数。在Scala中,我们可以在一个函数内定义函数,在其他函数内定义的函数被称为嵌套函数或局部函数。
语法:
def FunctionName1( perameter1, peramete2, ..) = {
def FunctionName2() = {
// code
}
}
// Scala program of Single Nested Function
object MaxAndMin
{
// Main method
def main(args: Array[String])
{
println("Min and Max from 5, 7")
maxAndMin(5, 7);
}
// Function
def maxAndMin(a: Int, b: Int) = {
// Nested Function
def maxValue() = {
if(a > b)
{
println("Max is: " + a)
}
else
{
println("Max is: " + b)
}
}
// Nested Function
def minValue() = {
if (a < b)
{
println("Min is: " + a)
}
else
{
println("Min is: " + b)
}
}
maxValue();
minValue();
}
}
输出:
Min and Max from 5, 7
Max is: 7
Min is: 5
Scala中的Currying函数 :
Scala中的Currying只是一种技术,或者说是一种转换函数的过程。这个需要多个参数的函数变成了需要单个参数的函数。
语法 :
def function name(argument1, argument2) = operation
// Scala program add two numbers
// using currying Function
object Curry
{
// Define currying function
def add(x: Int, y: Int) = x + y;
def main(args: Array[String])
{
println(add(20, 19));
}
}
输出:
39
面向对象的编程
面向对象编程的目的是在编程中实现现实世界的实体,如继承、隐藏、多态性等。OOP的主要目的是将数据和对其进行操作的函数绑定在一起,这样除了该函数外,代码的其他部分都不能访问这些数据。
OOPs的概念:
- 多态性
- 继承
- 抽象-类
- 类和对象
- 构造函数
类和对象的创建:
类和对象是面向对象编程的基本概念,围绕着现实生活中的实体。类是一个用户定义的蓝图或原型,对象是由它创建的。
// A Scala program to illustrate
// how to create a class
// Name of the class is Smartphone
class Smartphone
{
// Class variables
var number: Int = 16
var nameofcompany: String = "Apple"
// Class method
def Display()
{
println("Name of the company : " + nameofcompany);
println("Total number of Smartphone generation: " + number);
}
}
object Main
{
// Main method
def main(args: Array[String])
{
// Class object
var obj = new Smartphone();
obj.Display();
}
}
输出
Name of the company : Apple
Total number of Smartphone generation: 16
特征
Traits就像Java中的接口。但是它们比Java中的接口更强大,因为在traits中你可以实现成员。特征可以有方法(包括抽象的和非抽象的)和字段作为其成员。
创建一个特征 –
// Scala program to illustrate how to
// create traits
// Trait
trait MyTrait
{
def pet
def pet_color
}
// MyClass inherits trait
class MyClass extends MyTrait
{
// Implementation of methods of MyTrait
def pet()
{
println("Pet: Dog")
}
def pet_color()
{
println("Pet_color: White")
}
// Class method
def pet_name()
{
println("Pet_name: Dollar")
}
}
object Main
{
// Main method
def main(args: Array[String])
{
val obj = new MyClass();
obj.pet();
obj.pet_color();
obj.pet_name();
}
}
输出 :
Pet: Dog
Pet_color: White
Pet_name: Dollar
正则表达式
正则表达式解释了一种用于匹配一系列输入数据的常见模式,因此它在众多编程语言中的模式匹配中很有帮助。在Scala中,正则表达式一般被称为Scala Regex。
// Scala program for Regular
// Expressions
// Creating object
object GfG
{
// Main method
def main(args
: Array[String])
{
// Applying r() method
val portal = "GeeksforGeeks".r
val CS
= "GeeksforGeeks is a CS portal."
// Displays the first match
println(portal findFirstIn CS)
}
}
输出 :
Some(GeeksforGeeks)
异常
异常是指在程序执行过程中(即运行时)发生的不想要的或意外的事件。这些事件会改变程序执行中的流程控制。
在Scala中,所有的异常都是未检查的。没有检查异常的概念,Scala在选择是否捕捉异常方面提供了很大的灵活性。
抛出异常 :
// Scala program of throw keyword
// Creating object
object Main
{
// Define function
def validate(article:Int)=
{
// Using throw keyword
if(article < 20)
throw new ArithmeticException("You are not eligible for internship")
else println("You are eligible for internship")
}
// Main method
def main(args: Array[String])
{
validate(22)
}
}
输出 :
You are eligible for internship
Try-Catch 异常 :
// Scala program of try-catch Exception
import java.io.IOException
// Creating object
object GFG
{
// Main method
def main(args:Array[String])
{
try
{
var N = 5/0
}
catch
{
// Catch block contain cases.
case i: IOException =>
{
println("IOException occurred.")
}
case a : ArithmeticException =>
{
println("Arithmetic Exception occurred.")
}
}
}
}
输出 :
Arithmetic Exception occurred.
文件处理
文件处理是一种将获取的信息存储在文件中的方法。Scala提供了一些包,我们可以从中创建、打开、读取和写入文件。在Scala中,为了向文件写入,我们从Java中借用了java.io._,因为在Scala标准库中,我们没有向文件写入的类。我们还可以导入java.io.File和java.io.PrintWriter。
- 创建一个新的文件。
- java.io.File定义了用于JVM访问文件、文件系统和属性的类和接口。
- File(String pathname)将参数字符串转换为抽象路径名,创建一个新的文件实例。
- 写入文件:
java.io.PrintWriter包括PrintStream中包含的所有打印方法。
以下是创建新文件并写入文件的实现。
// Scala File handling program
import java.io.File
import java.io.PrintWriter
// Creating object
object Geeks
{
// Main method
def main(args:Array[String])
{
// Creating a file
val file_Object = new File("abc.txt" )
// Passing reference of file to the printwriter
val print_Writer = new PrintWriter(file_Object)
// Writing to the file
print_Writer.write("Hello, This is Geeks For Geeks")
// Closing printwriter
print_Writer.close()
}
}
- 读取文件 :
以下是读取文件的例子。
// Scala File handling program
import scala.io.Source
// Creating object
object GeeksScala
{
// Main method
def main(args : Array[String])
{
// file name
val fname = "abc.txt"
// creates iterable representation
// of the source file
val fSource = Source.fromFile(fname)
while (fSource.hasNext)
{
println(fSource.next)
}
// closing file
fSource.close()
}
}
要了解更多关于各种不同的文件处理,请参考《 Scala中的文件处理 》
Scala集合
列表
列表是一个包含不可变数据的集合。列表在Scala中代表链接列表。Scala List类持有一个有顺序的、线性的项目列表。在Scala中,列表是不可变的,而数组是可变的。在Scala列表中,每个元素都必须是相同的类型。列表是在scala.collection.immutable包中定义的。
语法:
val variable_name: List[type] = List(item1, item2, item3)
or
val variable_name = List(item1, item2, item3)
创建和初始化Scala列表
示例:
// Scala program to print immutable lists
import scala.collection.immutable._
// Creating object
object GFG
{
// Main method
def main(args:Array[String])
{
// Creating and initializing immutable lists
val mylist1: List[String] = List("Geeks", "GFG",
"GeeksforGeeks", "Geek123")
val mylist2 = List("C", "C#", "Java", "Scala",
"PHP", "Ruby")
// Display the value of mylist1
println("List 1:")
println(mylist1)
// Display the value of mylist2 using for loop
println("\nList 2:")
for(mylist<-mylist2)
{
println(mylist)
}
}
}
输出 :
List 1:
List(Geeks, GFG, GeeksforGeeks, Geek123)
List 2:
C
C#
Java
Scala
PHP
Ruby
Map
Map是一个键值对的集合。换句话说,它类似于字典。键总是唯一的,而值不一定是唯一的。为了使用易变的Map,我们必须明确地导入scala.collection.mutable.Map类。
创建一个Map并访问其值
示例:
// Scala map program of
// Accessing Values Using Keys
// Creating object
object GFG
{
// Main method
def main(args:Array[String])
{
val mapIm = Map("Ajay" -> 30,
"Bhavesh" -> 20,
"Charlie" -> 50)
// Accessing score of Ajay
val ajay = mapIm("Ajay")
println(ajay)
}
}
输出 :
30
要了解更多关于地图的信息,请参考《Scala中的地图》。
。
迭代器
迭代器是一种逐一访问集合元素的方式。它在语法上类似于集合,但在功能上却有所不同。为了访问元素,我们可以使用hasNext()来检查是否有可用的元素,使用next()来打印下一个元素。
语法:
val v = Iterator(5, 1, 2, 3, 6, 4)
//checking for availability of next element
while(v.hasNext)
//printing the element
println(v.next)
例如:
//Scala iterator program
//for defining iterator
//Creating object
object GFG
{
// Main method
def main(args:Array[String])
{
val v = Array(5, 1, 2, 3, 6, 4)
//val v = List(5, 1, 2, 3, 6, 4)
// defining an iterator
// for a collection
val i = v.iterator
while (i.hasNext)
print(i.next + " ")
}
}
输出:
5 1 2 3 6 4
集合
集合是一个只包含唯一项目的集合。集合的唯一性是由集合所持有的类型的==方法定义的。如果你试图在集合中添加一个重复的项目,那么set会悄悄地丢弃你的请求。
语法:
// Immutable set
val variable_name: Set[type] = Set(item1, item2, item3)
or
val variable_name = Set(item1, item2, item3)
// Mutable Set
var variable_name: Set[type] = Set(item1, item2, item3)
or
var variable_name = Set(item1, item2, item3)
创建和初始化不可变集
示例:
// Scala program to illustrate the
// use of immutable set
import scala.collection.immutable._
object Main
{
def main(args: Array[String])
{
// Creating and initializing immutable sets
val myset1: Set[String] = Set("Geeks", "GFG",
"GeeksforGeeks", "Geek123")
val myset2 = Set("C", "C#", "Java", "Scala",
"PHP", "Ruby")
// Display the value of myset1
println("Set 1:")
println(myset1)
// Display the value of myset2 using for loop
println("\nSet 2:")
for(myset<-myset2)
{
println(myset)
}
}
}
输出 :
Set 1:
Set(Geeks, GFG, GeeksforGeeks, Geek123)
Set 2:
Scala
C#
Ruby
PHP
C
Java
创建和初始化可变集合
例子:
// Scala program to illustrate the
// use of mutable set
import scala.collection.immutable._
object Main
{
def main(args: Array[String])
{
// Creating and initializing mutable sets
var myset1: Set[String] = Set("Geeks", "GFG",
"GeeksforGeeks", "Geek123")
var myset2 = Set(10, 100, 1000, 10000, 100000)
// Display the value of myset1
println("Set 1:")
println(myset1)
// Display the value of myset2
// using a foreach loop
println("\nSet 2:")
myset2.foreach((item:Int)=>println(item))
}
}
输出 :
Set 1:
Set(Geeks, GFG, GeeksforGeeks, Geek123)
Set 2:
10
100000
10000
1000
100
元组(Tuple
元组是一个元素的集合。元组是异质性的数据结构,也就是说,它们可以存储不同数据类型的元素。元组是不可变的,不像Scala中的数组是可变的。
创建元组并访问一个元素
例子:
// Scala program to access
// element using underscore method
// Creating object
object gfg
{
// Main method
def main(args: Array[String])
{
var name = (15, "chandan", true)
println(name._1) // print 1st element
println(name._2) // print 2st element
println(name._3) // print 3st element
}
}
输出 :
15
chandan
true