zoukankan      html  css  js  c++  java
  • Scala-基础知识

    1.var,val和def三个关键字之间的区别?

    1. Scala声明变量有两种方式,一个用val,一个用var。

      val / var 变量名 : 变量类型 = 变量值。

      val定义的值是不可变的,它不是一个常量,是不可变量,或称之为只读变量。

      var 定义变量,val定义不可变量(val是java的final不可变变量,var是java的普通变量),变量和常量类型可以省略不写,自动推断;在main函数里,val和var仅声明变量;在class类定义里,val和var是先声明field存储空间,然后分别为他们定了同名的方法;

      var 变量定义了 同名方法(类似getter) 来获取它的变量值,同时提供了修改变量值的方法(类似于setter)

      var 修饰的对象引用可以改变,val 修饰的则不可改变,但对象的状态是可以改变的

      在应用过程中,尽可能地使用不可变变量。变量类型可以省略,解析器会根据值进行推断。val和var声明变量时都必须初始化。

      用def定义的成员变量,不具备setter和getter方法

      def 定义函数时,每一次重新获得一个函数

      def 函数名(参数名1: 参数类型1, 参数名2: 参数类型2) : 返回类型 = {函数体}

      def 和 val的关系是call-by-name和call-by-value的关系,def对应的是by-name,val对应的是by-value

      其中:call-by-value是在调用函数之前计算;call-by-name是在需要时计算

      还有一个lazy val(惰性val)声明,当需要计算时才使用,避免重复计算

    2. trait(特质)和abstract class(抽象类)的区别?

      trait:

      Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。

      与接口不同的是,它还可以定义属性和方法的实现。

      一般情况下Scala的类可以继承多个Trait,从结果来看是实现了多重继承。Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait。

      特质是一些字段和行为的集合,可以扩展或混入(mixin)类中,通过with关键字,一个类可以扩展多个特质。

      1.优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。

      2.如果需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行。

      abstract class:

      抽象类定义了一些方法但没有实现他们。取而代之的是有扩展抽象类的子类定义这些方法。不能创建抽象类的实例。

      在Scala中重写一个非抽象方法必须使用override修饰符。调用超类的方法就如Java一样,使用super关键字。

    3. object和class的区别?

      object:

      Scala中没有静态修饰符,static,在object下的成员全部都是静态的,如果在类中声明了与该类相同的名字的object则该object是该类的“半生对象”。

      所以在scala中用object来实现这些功能,直接用对象名调用的方法都是采用这种实现方式,例如Array.toString。对象的构造器在第一次使用的时候会被调用,如果一个对象从未被使用,那么他的构造器也不会被执行;对象本质上拥有类(scala中)的所有特性,除此之外,object还可以一扩展类以及一个或者多个特质,object不能提供构造器参数,object必须是无参的,main方法都必须在object中被调用,提供程序的主入口。

      可以理解把类中的static集中放到了object对象中,伴生对象和类文件必须是同一个源文件,可以用伴生对象做一些初始化的操作。

      class:

      和java中的class类似。在Scala声明private变量会Scala编译器会自动生成get,set,在Scala中变量是需要初始化的,如果不声明private默认是public的

      trait:

      在java中可以通过interface实现多重继承,在Scala中可以通过特征(trait)实现多重继承,不过与java不同的是,

      它可以定义自己的属性和实现方法体,在没有自己的实现方法体时和java interface是等价的,在Scala中也是一般只能继承一个父类,可以通过多个with进行多重继承。

    4. 伴生对象是什么?

      在Scala中,伴生对象就是与类名相同的对象。并且所在的类被称为伴生类。

      伴生对象可以访问类中的私有量,类也可以访问伴生对象中的私有方法,类似于Java类中的静态方法。伴生对象必须和其对应的类定义在相同的源文件。

    5. Scala类型系统中Nil, Null, None, Nothing四个类型的区别?

      Null是一个trait(特质),是所有引用类型AnyRef的一个子类型,null是Null唯一的实例。
      Nothing也是一个trait(特质),是所有类型Any(包括值类型和引用类型)的子类型,它不在有子类型,它也没有实例,实际上为了一个方法抛出异常,通常会设置一个默认返回类型。
      Nil代表一个List空类型,等同List[Nothing]
      None是Option monad的空标识

    6. Unit类型是什么?

      表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。

    7. Option类型的定义和使用场景?

      Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。

      Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。

      Option 有两个子类别,一个是 Some,一个是 None,当他回传 Some 的时候,代表这个函式返回一个 String,可以通过 get() 这个函式拿到那个 String,如果返回的是 None,则代表没有字符串。

      序号
      方法及描述
      1 def get: A获取可选值
      2 def isEmpty: Boolean检测可选类型值是否为 None,是的话返回 true,否则返回 false
      3 def productArity: Int返回元素个数, A(x_1, …, x_k), 返回 k
      4 def productElement(n: Int): Any获取指定的可选项,以 0 为起始。即 A(x_1, …, x_k), 返回 x_(n+1) , 0 < n < k.
      5 def exists(p: (A) => Boolean): Boolean如果可选项中指定条件的元素存在且不为 None 返回 true,否则返回 false。
      6 **def filter(p: (A) => Boolean): Option[A]**如果选项包含有值,而且传递给 filter 的条件函数返回 true, filter 会返回 Some 实例。 否则,返回值为 None 。
      7 **def filterNot(p: (A) => Boolean): Option[A]**如果选项包含有值,而且传递给 filter 的条件函数返回 false, filter 会返回 Some 实例。 否则,返回值为 None 。
      8 def getOrElse[B >: A](default: => B): B如果选项包含有值,则传递给函数 f 处理后返回,否则返回 None
      9 def foreach[U](f: (A) => U): Unit如果选项包含有值,则将每个值传递给函数 f, 否则不处理。
      10 def getOrElse[B >: A](default: => B): B如果选项包含有值,返回选项值,否则返回设定的默认值。
      11 def isDefined: Boolean如果可选值是 Some 的实例返回 true,否则返回 false。
      12 def iterator: Iterator[A]如果选项包含有值,迭代出可选值。如果可选值为空则返回空迭代器。
      13 **def map[B](f: (A) => B): Option[B]**如果选项包含有值, 返回由函数 f 处理后的 Some,否则返回 None
      14 def orElse[B >: A](alternative: => Option[B]): Option[B]如果一个 Option 是 None , orElse 方法会返回传名参数的值,否则,就直接返回这个 Option。
      15 def orNull如果选项包含有值返回选项值,否则返回 null。
    8. 解释隐示参数的优先权

      在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会在作用域内尝试寻找一个指定类型的,用implicit修饰的对象,即隐式值,并注入参数。

      在Scala中implicit的功能很强大。当编译器寻找implicits时,如果不注意隐式参数的优先权,可能会引起意外的错误。因此编译器会按顺序查找隐式关键字。

      顺序如下:
      (1)当前类声明的implicits ;
      (2)导入包中的 implicits;
      (3)外部域(声明在外部域的implicts);
      (4)inheritance
      (5)package object
      (6)implicit scope like companion objects

    9. 什么是函数柯里化?

      高阶函数(函数的返回类型是函数)的简化,是高阶函数的一种定义方式。

        def fun3(a: Int, b: Int)(c: Int, d: Int): Int = {
          a + b + c + d
        }
        println(fun3(1,2)(2,3))
      
    10. 什么是高阶函数?

      就是操作其他函数的函数

      1.函数的参数是函数,

      2.或者函数的返回类型是函数(必须显示的写出方法的返回值类型),

      3.或者函数的参数和函数的返回类型是函数的函数。

    11. yield如何工作?

      yield用于循环迭代中生成新值,yield是comprehensions的一部分,是多个操作(foreach, map, flatMap, filter or withFilter)的composition语法糖。comprehension(推导式)是若干个操作组成的替代语法。如果不用yield关键字,comprehension(推导式)可以被forech操作替代,或者被map/flatMap,filter代替。

    12. 偏应用函数和偏函数的区别

      偏函数:

      是一个数学概念它不是"函数"的一种, 它跟函数是平行的概念。
      Scala中的Partia Function是一个Trait,其的类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果。

      偏函数内部有一些方法,比如isDefinedAt、OrElse、 andThen、applyOrElse等等。

      偏应用函数:

      偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供一部分,或不提供所需参数。是一个逻辑上概念。

      偏应用函数类似于柯里化。

    13. case class (样本类)是什么?

    用于描述不可变的值对象(Value Object)。

    Scala的case Class就是在普通的类定义前加case这个关键字,然后可以对这些类来模式匹配。case Class支持模式匹配:

    样本类JsBoolean是一个持有Boolean值的JSON对象

    判断一个对象是否是某个类的对象,跟Java一样可以使用isInstanceOf。

    样本类的特点:

    • 隐式地声明字段为val
    • 自动混入特质ProductN
    • 自动地生成equals, canEqual, hashCode, toString, copy等方法;
    • 伴生对象中自动生成apply, unapply方法。

    不过,样本类扩大了类的空间及其对象的大小。

    样本类是一种特殊的类,它经过优化以被用于模式匹配。

    一个模式匹配包含了一系列备选项,每个都开始于关键字case。每个备选项都包含了一个模式及一到多个表达式,在模式匹配过程中被计算。

    package com.stu.array
    
    object CaseClass {
    
      def main(args: Array[String]): Unit = {
        println(cal("+"))
    
        prtList(List(0, 1))
    
        println(prtType("abc"))
        println(prtType(Map(1 -> 1)))
      }
    
      def cal(exp: String): Int = {
        val add = "+"
        val result = 1
        exp match {
          case "+" => result + 2 //常量模式仅仅匹配自身
          case "-" => result - 2
          case "*" => result * 2
          case "/" => result / 2
          case add => result + 2 //变量模式可以匹配任意对象
          case _ => result //通配模式匹配任意对象
        }
      }
    
      //序列模式
      def prtList(list: List[Int]) = list match {
        case List(0, _, _) => println("this is a list") //序列模式,可以匹配List或者Array
        case List(1, _*) => println("this is a list, too") //匹配一个不指定长度的序列
        case _ => println("other")
      }
    
      //元组模式
      def prtTuple(tup: Any) = tup match {
        case (0, _, _) => println("this is a tuple") //元组模式
        case _ => println("other")
      }
    
      //类型模式,可以用在类型测试和类型转换
      def prtType(x: Any) = x match {
        case s: String => s.length
        case m: Map[_, _] => m.size
        case _ => 1
      }
    }
    
    
  • 相关阅读:
    面向对象设计原则之接口隔离原则
    面向对象设计原则之开闭原则
    [OOD]违反里氏替换原则的解决方案
    错误程序
    error: ‘for’ loop initial declarations are only allowed in C99 mode
    函数模板
    查找
    队列类模板
    栈类模板
    单链表的结点类模板
  • 原文地址:https://www.cnblogs.com/ernst/p/12819256.html
Copyright © 2011-2022 走看看