Spark面向对象编程基础

本文详细介绍了Scala的面向对象编程,包括类的定义、构造器、继承、特质、模式匹配和包的使用。讲解了类的成员可见性、方法定义、单例对象、抽象类、Option类以及模式匹配的match语句和case类。此外,还阐述了特质的混入以及包的定义和成员引用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录:

一、类

              1、类的定义

              2、类成员的可见性

              3、方法的定义

              4、构造器

二、对象

       1、单例对象

       2、单例对象——伴生对象和孤立对象

       3、apply方法和updata方法

三、继承

       1、抽象类

       2、扩展类

       3、类层次结构

       4、Option类

四、特质(trait)

       1、特质概述

       2、特质的定义

       3、把特质混入类中

       4、把多个特质混入类中

五、模式匹配

       1、match语句

       2、case类的匹配

六、包

       1、包的定义

       2、引用包成员


一、类

1、类的定义

class 类名字{     //类名字首字母大写
    //这里定义类的字段和方法
}

字段valvar关键字进行定义

方法定义:def 方法名(参数列表):返回结果类型={方法体}

返回结果类型为“Unit”的时候表示无返回值。

2、类成员的可见性

Scala所有成员的默认可见性为公有任何作用域内都能直接访问公有成员。

除了默认的公有可见性,Scala也提供privateprotected,其中,private成员只对本类型和嵌套类型可见;protected成员对本类型和其继承类型都可见。

为了避免直接暴露public字段建议将字段设置为private对于private字段Scala采用类似Java中的getter(读取变量值)setter(写入新的值)方法,定义了两个成对的方法valuevalue_=进行读取和修改。“value_=”完整组合在一起是个方法名称。

(在/usr/local/scala/mycode路径下,创建一个名为Counter.scala的文件)

Scala语法中有如下规范:当编译器看到以valuevalue_=这种成对形式出现的方法时,它允许用户去掉下划线_,而采用类似赋值表达式的形式

3、方法的定义

基本语法:def 方法名(参数列表):返回结果类型={ 方法体 }

方法参数前不能加上valvar所有的方法参数都是不可变类型

无参数的方法定义时可以省略括号,调用时也不能带有括号;

   例:定义时:  调用时:

•有参数的方法定义时带有括号,则调用时可以带括号,也可以不带括号。

   例:定义时:   调用时:

方法名后面的圆括号()可以用大括号{}来代替。

如果方法只有一个参数,可以省略点号(.)而采用中缀操作符调用方法

  中缀操作符调用方法:例如:把a.+(b)写成a+b

如果方法体只有一条语句,可以省略方法体两边的大括号

相关实例:(在/usr/local/spark/bin/mycode目录路径下,创建一个名为Counter.scala的文件)

方法的返回结果类型可以从最后的表达式推断出时,可以省略结果类型;

如果方法返回类型为Unit,可以同时省略返回结果类型和等号,但不能省略大括号。

Scala允许方法重载。只要方法的完整签名方法名、参数类型列表、返回类型是唯一的,多个方法可以使用相同的方法名。

4、构造器

Scala类的定义主体就是类的构造器,称为主构造器。在类名之后用圆括号列出主构造器的参数列表。

主构造器的参数前可以使用valvar关键字,Scala内部将自动为这些参数创建私有字段,并提供对应的访问方法。

如果不希望将构造器参数成为类的字段,只需要省略关键字var或者val。

Scala类可以包含零个或多个辅助构造器(auxiliary constructor)。辅助构造器使用this进行定义,this的返回类型为Unit

每个辅助构造器的第一个表达式必须是调用一个此前已经定义的辅助构造器或主构造器,调用的形式为“this(参数列表)”

相关实例:(在/usr/local/spark/bin/mycode目录路径下,创建一个名为Counter1.scala的文件)

二、对象

1、单例对象

Scala采用单例对象(singleton object)来实现与Java静态成员同样的功能。

使用object 关键字定义单例对象。

2、单例对象——伴生对象和孤立对象

当一个单例对象和它的同名类一起出现时,这时的单例对象被称为这个同名类的“伴生对象” companion object)。相应的类被称为这个单例对象的“伴生类”

类和它的伴生对象必须存在于同一个文件中,可以相互访问私有成员。

没有同名类的单例对象,被称为孤立对象(standalone object)。一般情况下,Scala程序的入口点main方法就是定义在一个孤立对象里。

相关实例:(在/usr/local/spark/bin/mycode目录路径下,创建一个名为Person1.scala的文件)

3、apply方法和update方法

(1)、apply方法

val myStrArr = Array("BigData","Hadoop","Spark")

Scala自动调用Array类的伴生对象Array中的一个称为apply的方法,来创建一个Array对象myStrArr

apply方法调用约定:用括号传递给类实例或单例对象名一个或多个参数时,Scala 会在相应的类或对象中查找方法名为apply且参数列表与传入的参数一致的方法,并用传入的参数来调用该apply方法。

例:类中的apply方法((在/usr/local/spark/bin/mycode目录路径下,创建一个名为TestApplyClass.scala的文件)

伴生对象中的apply方法:将所有类的构造方法以apply方法的形式定义在伴生对象中,这样伴生对象就像生成类实例的工厂,而这些apply方法也被称为工厂方法。

为什么要设计apply方法?

保持对象和函数之间使用的一致性。

面向对象“对象.方法” VS  数学:“函数(参数)

Scala中一切都是对象,包括函数也是对象。Scala中的函数既保留括号调用样式,也可以使用点号调用形式,其对应的方法名      即为apply

Scala对象也可以看成函数,前提是该对象提供了apply方法

(2)、update方法

update方法的调用约定:当对带有括号并包括一到若干参数的对象进行赋值时,编译器将调用对象的update方法,并将括号里的参数和等号右边的值一起作为update方法的输入参数来执行调用。

三、继承

1、抽象类

如果一个类包含没有实现的成员,则必须使用abstract关键词进行修饰,定义为抽象类。

关于上面的定义,说明几点:
定义一个抽象类,需要使用关键字abstract。
定义一个抽象类的抽象方法,不需要关键字abstract,只要把方法体空着,不写方法体就可以。
抽象类中定义的字段,只要没有给出初始化值,就表示是一个抽象字段,但是,抽象字段必须要声明类型,否则编译会报错。

2、扩展类

Scala只支持单一继承,而不支持多重继承。在类定义中使用extends关键字表示继承关系。

定义子类时,需要注意:

 

重载父类的抽象成员(包括字段和方法)时,override关键字是可选的;重载父类的非抽象成员时,override关键字是必选的。

只能重载val类型的字段,而不能重载var类型的字段。因为var类型本身就是可变的,可以直接修改它的值,无需重载;

子类不仅仅可以派生自抽象类,还可以派生自非抽象类,如果某个类不希望被其它类派生出子类,则需要在类定义的class关键字前加上final关键字。

子类如果没有显式地指明父类,则其默认的父类为AnyRef

3、类层次结构

Null是所有引用类型的子类,其唯一的实例为null,表示一个“空”对象,可以赋值给任何引用类型的变量,但不能赋值给值类型的变量。

Nothing是所有其它类型的子类,包括NullNothing没有实例,主要用于异常处理函数的返回类型。

4、Option

Scala提供null是为了实现在JVM与其它Java库的兼容性,但是,除非明确需要与Java库进行交互,否则,Scala建议尽量避免使用这种可能带来bugnull,而改用Option类。

Option是一个抽象类,有一个具体的子类Some和一个对象None,其中,前者表示有值的情形,后者表示没有值。

当方法不确定是否有对象返回时,可以使用方法Option[T],其中,T为类型参数。对于这类方法,如果确实有T类型的对象需要返回,会将该对象包装成一个Some对象并返回;如果没有值需要返回,将返回None

四、特质(trait)

1、特质概述

Java中提供了接口,允许一个类实现任意数量的接口。

Scala中没有接口的概念,而是提供了“特质(trait)”,它不仅实现了接口的功能,还具备了很多其他的特性。

Scala的特质是代码重用的基本单元,可以同时拥有抽象方法和具体方法。

Scala中,一个类只能继承自一个超类,却可以实现多个特质,从而重用特质中的方法和字段,实现了多重继承。

2、特质的定义

使用关键字trait

特质既可以包含抽象成员,也可以包含非抽象成员。包含抽象成员时,也不需要abstract关键字

特质可以使用extends继承其它的特质,并且还可以继承类。

特质的定义体就相当于主构造器,与类不同的是,不能给特质的主构造器提供参数列表,而且也不能为特质定义辅助构造器。

3、把特质混入类中

可以使用extendswith关键字把特质混入类中。如果特质中包含抽象成员,则该类必须为这些抽象成员提供具体实现,除非该类被定义为抽象类。 

特质也可以当做类型使用,即可以定义具有某种特质类型的变量,并使用任何混入了相应特质的类的实例进行初始化。

当使用extends关键字混入特质时,相应的类就隐式地继承了特质的超类。如果想把特质混入到需要显式指定了父类的类里,则可以用 extends 指明待继承的父类,再用 with 混入特质。

4、把多个特质混入类中

如果要混入多个特质,可以连续使用多个with

(Bird类一方面继承了父类Animal类,另一方面混入两个特质)

五、模式匹配

1、match语句

最常见的模式匹配是match语句,match语句用在当需要从多个分支中进行选择的场景。

通配符_相当于Java中的default分支。

match结构中不需要break语句来跳出判断,Scala从前往后匹配到一个分支后,会自动跳出判断。

case后面的表达式可以是任何类型的常量,而不要求是整数类型。

case 'A' => println("85-100")
case "China" => println("中国")
case _=> println("error input!")
case _=> println("外国")

•case后面除了匹配特定的常量,还能匹配某种类型的所有值。

可以在match表达式的case中使用守卫式(guard)添加一些过滤逻辑。

守卫表达式:for(变量 <- 表达式  if条件表达式){语句块}

2、case类的匹配

case类是一种特殊的类,它们经过优化已被用于模式匹配。

当定义一个类时,如果在class关键字前加上case关键字,则该类称为case类。

Scalacase类自动重载了许多实用的方法,包括toStringequalshashcode方法。

Scala为每一个case类自动生成一个伴生对象,其包括模板代码:

       一个apply方法,因此,实例化case类的时候无需使用new关键字

       一个unapply方法,该方法包含一个类型为伴生类的参数,返回的结果是Option类型,对应的类型参数是N元组,N是伴生类         中主构造器参数的个数。Unapply方法用于对对象进行解构操作,在case类模式匹配中,该方法被自动调用,并将待匹配的          对象作为参数传递给它。

例如,假设有如下定义的一个case类:

case class Car(brand:String, price:Int)

则编译器自动生成的伴生对象是:

object Car{
    def apply(brand:String,price:Int) = new Car(brand,price)
    def unapply(c:Car):Option[(String,Int)] = Some((c.brand,c.price))
}

实例:代码文件为:/usr/local/spark/bin/mycode/TestCase.scala

每一个case子句中的Car(…),都会自动调用Car.unapply(car),并将提取到的值与Car后面括号里的参数进行一一匹配比较。

第一个case和第二个case是与特定的值进行匹配。

第三个case由于Car后面跟的参数是变量,因此将匹配任意的参数值。

六、包

1、包的定义

为了解决程序中命名冲突问题,Scala也和Java一样采用包(package)来层次化、模块化地组织程序。

包可以包含类、对象和特质的定义,但是不能包含函数或变量的定义。

         

为了在任意位置访问MyClass类,需要使用autodepartment.MyClass。

Scala的包和源文件之间并没有强制的一致层次关联关系。

通过在关键字package后面加大括号,可以将程序的不同部分放在不同的包里。这样可以实现包的嵌套,相应的作用域也是嵌套的。

package xmu{
    package autodepartment{
        class ControlCourse{
            ······
        }
    }
    package csdepartment{
        class OSCourse{
            val cc = new autodepartment.ControlCourse
        }
    }
}

2、引用包成员

可以用import 子句来引用包成员,这样可以简化包成员的访问方式

import xmu.autodepartment.ControlCourse
class MyClass{
    var myos = new ControlCourse
}

使用通配符下划线(_)引入类或对象的所有成员

import scala.io.StdIn._
var i = readInt()
var f = readFloat()
var str = readLine()

Scala 隐式地添加了一些引用到每个程序前面,相当于每个Scala程序都隐式地以如下代码开始

import java.lang._
import scala._
import Predef._

java.lang 包定义了标准Java类;scala包定义了标准的Scala类库Predef 对象包含了许多Scala程序中常用到的类型、方法和隐式转换的别名定义,例如,前文讲到的输出方法,可以直接写println,而不是Predef.println

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值