zoukankan      html  css  js  c++  java
  • Scala语言学习

    Scala的程序被编译成Java字节码(生成class文件),所以可以运行在JVM上,并且可以调用Java的类库,兼容Java程序。

    Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成OOP和函数式编程(FP)的各种特性:

    1. 面向对象特性:Scala是一种纯面向对象的语言,每个值都是对象。类名:采用PascalCase命名(如class MyFirstScalaClass)。方法名:采用camleCase命名(如def myMethodName())。与Java类似,变量命名也采用camelCase方式。Scala类扩展有两种途径:一种途径是子类继承(单继承),另一种途径是灵活的混入机制。这两种途径能避免多重继承的种种问题。
    2. 函数式编程:即函数也能当成值来使用。可以定义匿名函数、高阶函数、多层嵌套函数,并支持柯里化。Scala的case class、内置的模式匹配相当于FP的代数类型。利用Scala的模式匹配可以处理XML数据(这个过程类似于正则表达式)。
    3. 静态类型:即Scala具有的类型系统,编译时先检查类型,保证了代码的安全性、一致性。类型系统包含:泛型类、协变和逆变、标注、类型参数的上下限约束、把类别和抽象类型作为对象成员、复合类型、引用自己时显示指定类型、视图、多态方法。
    4. 扩展性:
    5. 并发性:使用Actor作为并发模型,但它不同于Thread,它相当于Thread的实体。在Scala中,多个Actor可以分别复用/使用同一个线程,因此可以在程序中可以使用数百万个Actor,而线程只能创建数千个,在2.10之后的版本中,使用Akka作为其默认Actor实现。Actor通过邮箱收发消息。——线程复用:线程的数量必须加以控制,因为盲目的大量创建线程反而会降低系统性能。于是不狂增数量,而是将已创建的线程进行重复使用,即线程使用完毕,不立即销毁,而是暂时放在连接池(其状态肯定是空闲了),以供下次可以继续使用这些已有的线程,而不必创建新的。

    Scala比较流行的Web框架:Lift框架、Play框架。

    1、脚本编程:运行一个HelloWorld的程序(保存到HelloWorld.scala文件中,文件名应与类名相同,否则无法编译):

    object HelloWorld {
        def main(args: Array[String]): Unit = {
            println("Hello, world!")
        }
    }

    在终端中,运行:scala HelloWorld.scala,即可输出。

    2、Scala也可以交互式编程(进入终端):

    当要使用的标识符(方法名等)与关键字冲突之时,要使用这个标识符就需要写在一对倒引号`之间,如线程的yield方法:Thread.`yield`()。

    定义Scala的包:

    1、第一种方法类似于Java,在一个文件开头定义包名,则该文件后面的所有代码都属于这个包:

    package com.qunyh;
    class HelloWorld() {
    }

    2、第二种方法类似于C#,指明包的作用域,于是一个文件中可以定义多个包:

    package com.qunyh {
        class HelloQunyh {
        }
    }

    引用包(可以引用Java的包):

    import java.awt.Color    //只引入Color类
    import java.awt._    //引入包内所有成员

    多行字符串:

    val foo = """菜鸟教程
    www.runoob.com
    www.w3cschool.cc
    www.runnoob.com
    以上三个地址都能访问""";    //这是一个字符串,只不过是分多行:在一对"""之间

    变量的声明:

    一般变量用var声明,常量用val声明(这种声明的常量值以后就不能修改了,不然编译会报错)。

    //可以指明变量类型(这种声明的时候可以不用初始化): 注意类型的位置
    var myVar : String = "Foo";
    val myVal : String = "Foo";
    //也可以不指明(此时必须初始化,才能类型推断)
    var yourVar = "Foo";
    val yourVal = "Foo";
    //多个变量一起声明
    var xmax, ymax = 100;    //两个变量值都为100

    声明一个元组:

    访问修饰符:

    基本和Java一样,如果没有指定,默认访问级别是public。但是Scala的限定比Java更严格。

    for循环:

    1、第一种结构是for( var x <- Range ):其中Range区间可以是i to j或者i until j;而左箭头<-用于为变量x赋值。

    object HelloWorld {
        def main(args: Array[String]): Unit = {
            var x = 0;
            //for(x <- 1 to 10)
            for(x <- 1 until 10) {
                println("hello");
            }
        }
    }
    object Test {
       def main(args: Array[String]) {
          var a = 0;
          var b = 0;
          // 相当于二重循环:
          //for(int a = 1; a <= 3; a++)
          //    for(int b = 1; b <= 3; b++)
          for( a <- 1 to 3; b <- 1 to 3){
             println( "Value of a: " + a );
             println( "Value of b: " + b );
          }
       }
    }

    2、第二种结构for( var x <- List ):其中 List 变量是一个集合,for 循环会迭代所有集合的元素:

    object Test {
        def main(args: Array[String]) {
            var a = 0;
            var numList = List(1, 2, 3, 4);
            for(a <- numList) {
                println(a + "");
            }
        }
    }

    与其他的动态语言类似,Scala也有过滤器:

    object Test {
        def main(args: Array[String]) {
            var a = 0;
            var numList = List(1,2,3,4,5,6,7,8,9,10);
            for(a <- numList
                if a % 2 == 0; if a < 5) {
                    println(a + "");
            }
        }
    }

    而且还可以把List中过滤后剩下的,作为新的List返回(只是这种for循环的写法有点不同):

    object Test {
        def main(args: Array[String]) {
            var a = 0;
            var numList = List(1,2,3,4,5,6,7,8,9,10);
            var retList = for{ a <- numList
                if a % 2 == 0; if a < 5 } yield a;    //这种for循环就不带循环体了
            for(a <- retList) {
                println(a + "");
            }
        }
    }

    Scala的循环控制语句没有break、continue等,但是提供了另一种语法来实现break语句的效果(需要导入control包)。

    import scala.util.control._
    object Test {
        def main(args: Array[String]) {
            var a = 0;
            var control = new Breaks;
            var numList = List(1,2,3,4,5,6,7,8,9,10);
            //建议
            control.breakable {
                for(a <- numList) {
                    println(a + "");
                    if(a == 5) {
                        control.break;
                    }
                }
            }
            for(a <- numList) {
                println(a + "");
                if(a == 5) {
                    control.break;
                }
            }
        }
    }

    函数

    Scala 有函数和方法,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。我们可以在任何地方定义函数,甚至可以在函数内定义函数(内嵌函数),但是作用域就受到了限制。

    Scala 函数声明格式如下:

    def functionName ([参数列表]) : [return type];

    如果不写等于号和方法主体(只有声明),那么方法会被隐式声明为"抽象(abstract)",包含它的类型(在类中)于是也是一个抽象类型。

    函数定义格式如下(含body),其中返回值可以是任意的Scala数据类型:

    def functionName ([参数列表]) : [return type] = {
        function body
        return [expr]
    }

    闭包:

    Scala的闭包与C#的Lambda表达式类似,例如:

    val multiplier = (i:Int) => i * factor;    //这就是一个闭包:箭头的左边是形参,右边是body(可能含返回值)。整个闭包可以当作一个函数,赋给一个变量

    Scala的字符串:

    String类型:

    Scala本身没有String类,其类型实际上是Java String(java.lang.String),而Java的String对象的值是不可变的,如果修改字符串则意味着会产生一个新的字符串对象(暂时还没搞清楚,但我觉得是这个意思:修改之前=右边是一个字符串常量对象,变量只是引用其地址,而修改之后就是创建了一个新的字符串常量对象,变量只是更改其引用地址)。与Java、C#类似,要创建一个可修改的字符串,可以使用StringBuilder类。

    StringBuilder类:

    object Test {
        def main(args: Array[String]) {
            val buf = new StringBuilder;
            buf += 'a';
            buf ++= "bcdef";    //都不会重新创建对象
            println( "buf is : " + buf.toString );
        }
    }

    数组:

    var z = Array("Runoob", "Baidu", "Google");
    var z:Array[String] = new Array[String](3);
    //多维数组
    var myMatrix = ofDim[Int](3,3);
    //合并数组
    var myList1 = Array(1, 2, 3);
    var myList2 = Array(4, 5, 6);
    var myList3 =  concat( myList1, myList2);    //123456;concat函数:import Array._;
    //创建区间数组:使用range方法,返回一个数组Array
    var yourList1 = range(10, 20, 2);    //arg3是步长,默认为1(不包含20)

    集合:

    Scala提供了一些集合类型的抽象,分为可变集合、不可变集合。

    • 可变集合可以在适当的时候更新或扩展,即添加、移除、修改一个集合元素。
    • 不可变集合一旦创建,其本身永远不会改变。但是仍然可以"模拟"可变集合的操作,这些操作还是不会改变不可变集合本身,却可以返回一个新的集合(新集合是否可变)。
    // 常见的集合:
    // 定义整型 List
    val x = List(1,2,3,4)
    // 定义 Set
    var x = Set(1,3,5,7)
    // 定义 Map
    val x = Map("one" -> 1, "two" -> 2, "three" -> 3)
    // 创建一个元组(这里包含两个不同类型元素)
    val x = (10, "Runoob")
    // 定义 Option
    val x: Option[Int] = Some(5)

    迭代器Iterator:

    Iterator不是集合,而是一种访问集合的方法。迭代器的两个基本操作是next(返回集合中、迭代器的下一个元素,并更新迭代器自身的状态)和hasNext(判断集合中、迭代器的下一个元素是否存在)方法。可以先看代码,然后更容易理解:

    object Test {
        def main(args: Array[String]) {
            val it = Iterator("Baidu", "Google", "Runoob", "Taobao");
            while (it.hasNext){
                println(it.next())
            }
            //还可以利用迭代器,很方便的查找max、min
            var ita = Iterator(20,40,2,50,69, 90);
            println("最小:" + ita.min);
            //println("最小:" + ita.min);
            //println("最大:" + ita.max);    //一个迭代器,max、min只能用一次(再用就不支持操作),就算是用两次min也不行
            //我的理解是:迭代器是迭代地找max、min,找到即遍历完整个"集合",就停止迭代了,
            //再次使用就会抛出异常java.lang.UnsupportedOperationException
            
            //获取迭代器的长度size或length:即可以迭代的次数
            //和min、max的用法相似:所以第一次是6,以后就是0了
            var itb = Iterator(20,40,2,50,69, 90);
            println(itb.size + ":" + itb.length);
            //println(itb.size + ":" + itb.size);
        }
    }

    Scala类与对象:

    创建一个类和类的实例:

    //Point类文件
    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;
        println("x 的坐标为:" + x);
        println("y 的坐标为:" + y);
      }
    }
    //主函数
    object Test {
      def main(args: Array[String]) {
        //创建一个Point对象
        var pt = new Point(10, 20);
        pt.move(10, 10);
      }
    }

    Scala继承:

    //继承刚才的Point类:Location类文件
    class Location(override val xc: Int, override val yc: Int, val zc: Int) extends Point(xc, yc) {
      var z: Int = zc;
      
      def move(dx: Int, dy: Int, dz: Int) {
        x = x + dx;
        y = y + dy;
        z = z + dz;
        println("x 的坐标为:" + x);
        println("y 的坐标为:" + y);
        println("z 的坐标为:" + z);
      }
    }
    //主函数
    object Test {
      def main(args: Array[String]) {
        //创建一个Point对象
        var lc = new Location(10, 20, 10);
        lc.move(10, 10, 10);
      }
    }

    Scala Trait(特征):

    特征相当于Java的接口,但是Scala的特征功能却更为强大。与接口不同,特征可以定义属性,还可以定义方法的实现,而Java接口却不能有实现(只能是抽象方法,而且接口不能包含成员变量,除了 static 和 final 变量)。因此在这个方面Trait更像Java的抽象类(可以有抽象方法与非抽象方法),但是抽象类只能是单继承,所以我觉得在Java中,接口就像是抽象类的精简版(只有定义,没有实现),而Scala Trait则像是结合了抽象类、接口,就像是一种可以多继承(接口)的抽象类。

  • 相关阅读:
    Debian如何永久添加静态路由
    一句话换个说法的软件
    高级程序员简历,技术总监喜欢什么简历?
    CP936实际上是GBK,编码问题再次让我熬夜
    句子说法转换的软件,基于AI技术
    输入关键词自动生成文章(2020年人工智能写作)
    自动写文章的智能软件(基于AI写作)
    python调用接口,python接收post请求接口(附完整代码)
    人工智能是铁饭碗还是铁坑,看看人工智能博士怎么说
    远离外包公司,就是远离码农的血汗工厂
  • 原文地址:https://www.cnblogs.com/quanxi/p/6764368.html
Copyright © 2011-2022 走看看