• [2]SpinalHDL教程——Scala简单入门


    第一个 Scala 程序#

    shell里面输入

    Copy
    $ scala
    Copy
    scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World!

    文件形式

    Copy
    object HelloWorld { /* 这是我的第一个 Scala 程序 * 以下程序将输出'Hello World!' */ def main(args: Array[String]) = { println("Hello, world!") // 输出 Hello World } }

    接下来我们使用 scalac 命令编译它:

    Copy
    $ scalac HelloWorld.scala $ ls HelloWorld$.class HelloWorld.scala HelloWorld.class

    编译后我们可以看到目录下生成了 HelloWorld.class 文件,该文件可以在Java Virtual Machine (JVM)上运行。

    编译后,我们可以使用以下命令来执行程序:

    Copy
    $ scala HelloWorld Hello, world!

    基本语法#

    Scala是运行在jvm上面的一款语言,在语法和概念上难免和java会有相似之处,而java的语法和C语法一脉相承,所以有C基础的话基本语法还是比较好上手的。

    Scala有两个设计理念:面向对象(OOP)和函数式编程(FP)

    面向对象就导致Scala中万物皆对象;函数式这个概念比较陌生,后续会单独介绍。

    1.变量#

    使用关键词 "var" 声明变量,使用关键词 "val" 声明常量。

    声明变量实例如下:

    Copy
    var myVar : String = "Foo" var myVar : String = "Too"

    Scala是一个静态类型语言,但编译器能自动推断类型

    所以上面能这么写,效果一样:

    Copy
    var myVar = "Foo" var myVar = "Too"

    2.数据类型#

    然而,我们说scala是一款万物皆对象的语言,这些变量都是对象

    这就类似于java中的封装类(Scala的底层实现确实也是用的java的封装类)

    Scala 与 Java有着相同的数据类型,下表列出了 Scala 支持的数据类型:

    数据类型 描述
    Byte 8位有符号补码整数。数值区间为 -128 到 127
    Short 16位有符号补码整数。数值区间为 -32768 到 32767
    Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
    Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
    Float 32 位, IEEE 754 标准的单精度浮点数
    Double 64 位 IEEE 754 标准的双精度浮点数
    Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
    String 字符序列
    Boolean true或false
    Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
    Null null 或空引用
    Nothing Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。
    Any Any是所有其他类的超类
    AnyRef AnyRef类是Scala里所有引用类(reference class)的基类

    上表中列出的数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的。

    (1)整数字面量、浮点字面量#

    (2)字符串字面量#

    Copy
    scala> '1' res0: Char = 1 scala> "1" res1: String = 1 scala> "\t" res2: String = " " scala> """\t""" res3: String = \t

    字符串插值,会对每个表达式求值,并且调用toString方法

    Copy
    scala> val a=2.1 a: Double = 2.1 scala> val s=s"Hi,${a+9}!" s: String = Hi,11.1!

    函数#

    方法定义#

    方法定义由一个 def 关键字开始,紧接着是可选的参数列表,一个冒号 : 和方法的返回类型,一个等于号 = ,最后是方法的主体。

    Scala 方法定义格式如下:

    Copy
    def functionName ([参数列表]) : [return type] = { function body return [expr] }
    • 以上代码中 return type 可以是任意合法的 Scala 数据类型。参数列表中的参数可以使用逗号分隔。

    题外话:scala能使用元组进行打包,返回多个变量,在调用时解构赋值

    scala> def useScala() = (1,2,3)
    useScala: ()(Int, Int, Int)

    scala> val a,b,c = useScala()
    a: (Int, Int, Int) = (1,2,3)
    b: (Int, Int, Int) = (1,2,3)
    c: (Int, Int, Int) = (1,2,3)

    • 函数体最后一行的return推荐省略
    • 等号”=“省略条件:返回类型未显式声明,并且返回类型为Unit,这个类似于 Java 的 void, 实例如下:
    Copy
    object Hello{ def printMe( ){ println("Hello, Scala!") } }

    方法调用#

    以下是调用方法的标准格式:

    Copy
    functionName( 参数列表 )

    如果方法使用了实例的对象来调用,我们可以使用类似java的格式 (使用 . 号):

    Copy
    [instance.]functionName( 参数列表 )

    类和对象#

    类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。

    Copy
    class Point(xc: Int, yc: Int) { var x: Int = xc var y: Int = yc def move(dx: Int, dy: Int) { x = x + dx y = y + dy println ("x 的坐标点: " + x); println ("y 的坐标点: " + y); } }

    构造方法#

    1. 主构造方法

      在类内部非字段、非方法的部分全部当作构造函数,在类名后参数列表用于接收。

      可以看一个SpinalHDL生成verilog的写法:

      Copy
      object MyTopLevelVerilog extends App { Config.spinal.generateVerilog(MyTopLevel(4)) }

      看到App定义:

      Copy
      trait App extends DelayedInit { // ... @deprecatedOverriding("main should not be overridden", "2.11.0") def main(args: Array[String]) = { this._args = args for (proc <- initCode) proc() if (util.Properties.propIsSet("scala.time")) { val total = currentTime - executionStart Console.println("[total " + total + "ms]") } } }
    2. 辅助构造函数

      def this( ... )

      函数内第一句必须调用其他的构造方法this()

    3. 私有主构造方法

      如例所示加上private,构造对象时就不能通过主构造方法创建对象,得用辅助构造方法或工厂方法(用于构造对象的方法)

      Copy
      class Student private (name: String,n: Int)

    类继承#

    extends关键词

    Copy
    class Child extends Parent{ //... }

    工厂对象和工厂方法#

    如果定义一个专门用来构造某一个类的对象的方法,那么这种方法就被称为“工厂方法”。包含这些工厂方法集合的单例对象,称为“工厂对象”。通常,工厂方法会定义在伴生对象中。尤其是当一系列类存在继承关系时,可以在基类的伴生对象中定义一系列对应的工厂方法。使用工厂方法的好处是可以不用直接使用new来实例化对象,改用方法调用,而且方法名可以是任意的,这样对外隐藏了类的实现细节。

    Copy
    //students. scala class Students(val name:String,var score:Int){ def exam(s:Int)=score =s override def toString =name +"'s score is "+score +"." } object Students { def registerStu(name:String,score:Int)=new Students(name,score) } //registerStu为工厂方法

    用“ import Students._ ”导入单例对象后,就能这样使用:

    Copy
    scala>import Students._ scala>val stu =registerStu("Tim",100) stu:Students =Tim's score is 100.

    重写方法#

    在函数前面加上关键词override

    重写toString方法

    Copy
    class A { override def toString = "123456A" } val a = new A() println(a)
    Copy
    scala> class A { | override def toString = "123456A" | } // defined class A scala> val a = new A() val a: A = 123456A scala> println(a) 123456A

    Scala 单例对象#

    在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。

    Scala 中使用单例模式时,除了定义的类之外,还要定义一个同名的 object 对象,它和类的区别是,object对象不能带参数。

    当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员。

    Copy
    class Point(val xc: Int, val yc: Int) { var x: Int = xc var y: Int = yc def move(dx: Int, dy: Int) { x = x + dx y = y + dy } } object Test { def main(args: Array[String]) { val point = new Point(10, 20) printPoint def printPoint{ println ("x 的坐标点 : " + point.x); println ("y 的坐标点 : " + point.y); } } }

    执行以上代码,输出结果为:

    Copy
    $ scalac Test.scala $ scala Test x 的坐标点 : 10 y 的坐标点 : 20

    伴生对象#

    Copy
    // 私有构造方法 class Marker private(val color:String) { println("创建" + this) override def toString(): String = "颜色标记:"+ color } // 伴生对象,与类名字相同,可以访问类的私有属性和方法 object Marker{ private val markers: Map[String, Marker] = Map( "red" -> new Marker("red"), "blue" -> new Marker("blue"), "green" -> new Marker("green") ) def apply(color:String) = { if(markers.contains(color)) markers(color) else null } def getMarker(color:String) = { if(markers.contains(color)) markers(color) else null } def main(args: Array[String]) { println(Marker("red")) // 单例函数调用,省略了.(点)符号 println(Marker getMarker "blue") } }

    操作符即方法#

    1. 前缀操作符

      只有+、-、、!有,对应的方法名是unary_+、unary_-、unary_、unary_!

      2.中缀和后缀操作符

    ​ 以冒号结尾的操作符,右操作符是调用对象

  • 相关阅读:
    JAVA毕业设计html5健身房信息管理系统计算机源码+lw文档+系统+调试部署+数据库
    RuoYi_Cloud本地搭建
    高等教育的5个数字营销策略
    共载多西紫杉醇/依克立达人血清白蛋白纳米粒|白蛋白纳米粒可以包载多种药物
    CEAC之《职业素养》
    KoTime:v2.3.6-新增当前Java程序占用的内存统计以及页面刷新功能
    算法笔记:点四叉树
    2023/09/10
    5G 速率介绍
    任务七 特征工程 LDA
  • 原文地址:https://www.cnblogs.com/msuad/p/17335201.html