您当前的位置: 首页 >  大数据

庄小焱

暂无认证

  • 1浏览

    0关注

    805博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

大数据云计算——scala语言基本的语法

庄小焱 发布时间:2020-11-11 10:40:05 ,浏览量:1

Scala的基本语法 scala的变量的命名

scala的概念:1)Scala 对各种变量、方法、函数等命名时使用的字符序列称为标识符2)凡是自己可以起名字的地方都叫标识符

标识符的命名规则(记住):Scala中的标识符声明,基本和Java是一致的,但是细节上会有所变化。

1)首字符为字母,后续字符任意字母和数字,美元符号,可后接下划线_

2)数字不可以开头。

3)首字符为操作符(比如+ - * / ),后续字符也需跟操作符 ,至少一个(反编译)

4)操作符(比如+-*/)不能在标识符中间和最后.

5)用反引号`....`包括的任意字符串,即使是关键字(39个)也可以 [true]

标识符举例说明
hello    // ok
hello12 // ok
1hello  // error
h-b   // error
x h   // error
h_4   // ok
_ab   // ok
Int    // ok, 在scala中,Int 不是关键字,而是预定义标识符,可以用,但是不推荐
Float  // ok
_   // 不可以,因为在scala中,_ 有很多其他的作用,因此不能使用
Abc    // ok
+*-   // ok
+a  // error
scala的关键字
package, import, class, object, trait, extends, with, type, forSome
private, protected, abstract, sealed, final, implicit, lazy, override
try, catch, finally, throw 
if, else, match, case, do, while, for, return, yield
def, val, var 
this, super
new
true, false, null
  // ++ 和 --
    // 说明,在scala中没有 ++ 和 --, 而使用 +=1  和  -= 1
    var num1 = 10
    //num1++ 错误
    num1 += 1 // 替代 num1++
    //num-- 错误
    num1 -= 1 // 替代 num1--
    println(num1)
在scala的从键盘读取的函数
def main(args: Array[String]): Unit = {
    /*
    要求:可以从控制台接收用户信息,【姓名,年龄,薪水】
     */
    println("请输入姓名")
    val name = StdIn.readLine()
    println("请输入年龄")
    val age = StdIn.readInt()
    println("请输入薪水")
    val sal = StdIn.readDouble()
    printf("用户的信息为 name=%s age=%d sal=%.2f", name, age, sal)
    Cat.sayHi() //也是采用是一种的是调用的方式
    Cat.sayHello()
    Cat.sayHi()
    hi()
  }
scala的导包的是:import scala.math._ // _ 表示将scala.math 的所有内容导入 和java中的 import scala.math.*  // * 表示将scala.math 的所有内容导入

Scala异常处理小结:

7)finally子句用于执行不管是正常处理还是有异常发生时都需要执行的步骤,一般用于对象的清理工作,这点和Java一样。

8)Scala提供了throws关键字来声明异常。可以使用方法定义声明异常。 它向调用者函数提供了此方法可能引发此异常的信息。 它有助于调用函数处理并将该代码包含在try-catch块中,以避免程序异常终止。在scala中,可以使用throws注释来声明异常

def main(args: Array[String]): Unit = {
    f11()
  }
  @throws(classOf[NumberFormatException])//等同于NumberFormatException.class
  def f11()  = {
    "abc".toInt
  }

 scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public)

Scala构造器的基本语法

class 类名(形参列表) {  // 主构造器

   // 类体

   def  this(形参列表) {  // 辅助构造器

   }

   def  this(形参列表) {  //辅助构造器可以有多个...

   }

} 
//1. 辅助构造器 函数的名称this, 可以有多个,编译器通过不同参数来区分.

Scala构造器作用是完成对新对象的初始化,构造器没有返回值。
主构造器的声明直接放置于类名之后 

主构造器会执行类定义中的所有语句,这里可以体会到Scala的函数式编程和面向对象编程融合在一起,即:构造器也是方法(函数),传递参数和使用方法和前面的函数部分内容没有区别【案例演示+反编译】
如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略

如果想让主构造器变成私有的,可以在()之前加上private,这样用户只能通过辅助构造器来构造对象了

辅助构造器的声明不能和主构造器的声明一致,会发生错误(即构造器名重复)

package chapter06.constructor

object ConDemo04 {
  def main(args: Array[String]): Unit = {

    val worker = new Worker("smith")
    worker.name //不能访问 inName

    val worker2 = new Worker2("smith2")
    worker2.inName //可以访问 inName
    println("hello!")

    val worker3 = new Worker3("jack")
    worker3.inName = "mary"
    println(worker3.inName)
  }
}

//1. 如果 主构造器是Worker(inName: String) ,那么  inName就是一个局部变量
class Worker(inName: String) {
  var name = inName
}

//. 如果 主构造器是Worker2(val inName: String) ,那么  inName就是Worker2的一个private的只读属性
class Worker2(val inName: String) {
  var name = inName
}

// 如果 主构造器是Worker3(var inName: String) ,那么  inName就是Worker3的一个
// 一个private 的可以读写属性
class Worker3(var inName: String) {
  var name = inName
}
class Person {
  var age: Int = 90
  var name: String = _

  def this(n: String, a: Int) {
    this()
    this.name = n
    this.age = a
  }
  var p = new Person()
}


加载类的信息(属性信息,方法信息)
在内存中(堆)开辟空间
使用父类的构造器(主和辅助)进行初始
使用主构造器对属性进行初始化 【age:90, naem nul】
使用辅助构造器对属性进行初始化 【 age:20, naem 小倩 】
将开辟的对象的地址赋给 p这个引用

Scala中包的可见性介绍:在Java中,访问权限分为: public,private,protected和默认。在Scala中,你可以通过类似的修饰符达到同样的效果。但是使用上有区别。


Scala中包的可见性和访问修饰符的使用

当属性访问权限为默认时,从底层看属性是private的,但是因为提供了xxx_$eq()[类似setter]/xxx()[类似getter] 方法,因此从使用效果看是任何地方都可以访问)
当方法访问权限为默认时,默认为public访问权限
private为私有权限,只在类的内部和伴生对象中可用
protected为受保护权限,scala中受保护权限比Java中更严格,只能子类访问,同包无法访问 (编译器)
在scala中没有public关键字,即不能用public显式的修饰属性和方法。

Scala抽象类使用的注意事项和细节讨论

1)抽象类不能被实例

2)抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法

3)一旦类包含了抽象方法或者抽象属性,则这个类必须声明为abstract

4)抽象方法不能有主体,不允许使用abstract修饰。

5)如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法和抽象属性,除非它自己也声明为abstract类。

6)抽象方法和抽象属性不能使用private、final 来修饰,因为这些关键字都是和重写/实现相违背的。

7)抽象类中可以有实现的方法.

8)子类重写抽象方法不需要override,写上也不会错.

Scala的伴生对象

1)Scala中伴生对象采用object关键字声明,伴生对象中声明的全是 "静态"内容,可以通过伴生对象名称直接调用。

2)伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。

3)伴生对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问

4)从语法角度来讲,所谓的伴生对象其实就是类的静态方法和成员的集合

5)从技术角度来讲,scala还是没有生成静态的内容,只不过是将伴生对象生成了一个新的类,实现属性和方法的调用。

6)从底层原理看,伴生对象实现静态特性是依赖于 public static final  MODULE$ 实现的

7)伴生对象的声明应该和伴生类的声明在同一个源码文件中(如果不在同一个文件中会运行错误!),但是如果没有伴生类,也就没有所谓的伴生对象了,所以放在哪里就无所谓了。

8)如果 class A 独立存在,那么A就是一个类, 如果 object A 独立存在,那么A就是一个"静态"性质的对象[即类对象], 在 object A中声明的属性和方法可以通过 A.属性 和 A.方法 来实现调用

Scala接口的介绍

从面向对象来看,接口并不属于面向对象的范畴,Scala是纯面向对象的语言,在Scala中,没有接口。

Scala语言中,采用特质trait(特征)来代替接口的概念,也就是说,多个类具有相同的特征(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。 理解trait 等价于(interface + abstract class)

Scala中的trait

可以把特质可以看作是对继承的一种补充:Scala的继承是单继承,也就是一个类最多只能有一个父类,这种单继承的机制可保证类的纯洁性,比c++中的多继承机制简洁。但对子类功能的扩展有一定影响.所以我们认为: Scala引入trait特征 第一可以替代Java的接口,  第二个也是对单继承机制的一种补充

trait 的声明
trait 特质名 {
    trait体
}

trait 命名 一般首字母大写.

Cloneable , Serializable

object T1 extends Serializable {
}
Serializable: 就是scala的一个特质。
在scala中,java中的接口可以当做特质使用

Scala中trait 的使用

一个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字连接

没有父类 class  类名   extends   特质1   with    特质2   with   特质3 ..

有父类 class  类名   extends   父类   with  特质1   with   特质2   with 特质3

特质trait 的再说明

特质中没有实现的方法就是抽象方法。类通过extends继承特质,通过with可以继承多个特质

所有的java接口都可以当做Scala特质使用 

带有特质的对象,动态混入
除了可以在类声明时继承特质以外,还可以在构建对象时混入特质,扩展目标类的功能
此种方式也可以应用于对抽象类功能进行扩展
动态混入是Scala特有的方式(java没有动态混入),可在不修改类声明/定义的情况下,扩展类的功能,非常的灵活,耦合性低 。
动态混入可以在不影响原有的继承关系的基础上,给指定的类扩展功能
Scala中的隐式转换

隐式转换函数是以implicit关键字声明的带有单个参数的函数。这种函数将会自动应用,将值从一种类型转换为另一种类型。

implicit def f1(d: Double): Int = {
  d.toInt
}
//Double 是输入类型, Int 是转换后的类型
def main(args: Array[String]): Unit = {
      implicit def f1(d: Double): Int = {
        d.toInt
      }
      implicit def f2(l: Long): Int = {
        l.toInt
      }
      val num: Int = 3.5
      println(num)
      val num2: Int = 4.5
      println(num2)
      val num3: Int = 20l
 } 

隐式转换的注意事项和细节

1)隐式转换函数的函数名可以是任意的,隐式转换与函数名称无关,只与函数签名(函数参数类型和返回值类型)有关。

2)隐式函数可以有多个(即:隐式函数列表),但是需要保证在当前环境下,只有一个隐式函数能被识别

基本介绍

在scala2.10后提供了隐式类,可以使用implicit声明类,隐式类的非常强大,同样可以扩展类的功能,比前面使用隐式转换丰富类库功能更加的方便,在集合中隐式类会发挥重要的作用。

隐式类使用有如下几个特点:

1)其所带的构造参数有且只能有一个

2)隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是 顶级的(top-level  objects)。

3)隐式类不能是case class(case class在后续介绍 样例类)

4)作用域内不能有与之相同名称的标识符

关注
打赏
1657692713
查看更多评论
立即登录/注册

微信扫码登录

0.0653s