scala(2)

本文详细探讨了Scala中的类、object、抽象类、接口及其在Spark源码中的应用。讲解了Scala中变量与方法的特性,包括get/set方法的自动生成。此外,还介绍了伴生对象和伴生类的概念,以及apply方法的作用。同时,文章讨论了trait作为接口的使用,并分析了SparkContext和RDD类的部分源码,展示了Scala中的访问控制和final修饰符的用法。

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

第2课:Scala面向对象彻底精通及Spark源码阅读
本期内容:
1 Scala中的类、object实战详解
2 Scala中的抽象类、接口实战详解
3 综合案例及Spark源码解析

一:定义类
class HiScala{
private var name = "Spark"

def sayName(){
println(name)
}
def getName = name
}

Scala中,变量与类中的方法是同等级的,可以直接赋值给方法。

scala中的get与set与Java中的get,set有很大的差异:
在Scala中,如果程序中给变量或方法前面定义了private,那么scala会给这个变量或方法自动生成private的get和set方 
法,如果程序中没有给变量或方法前面定义了private,那么scala会给这个变量或方法变成 private 级别的字段或方法,自动生成 public 级别的 的getter和setter方法。

创建类的对象 
val scal = new Hiscala
scal.sayName()
scal.sayName//如果不传参时,等同上面
scal.getName

修改上面的类,并创建对象:

var name="Spark" //如果不加private,默认会生成一个public的get和set方法,外部可以调

println(scala.name) 可以打印出 name 的值。-->访问的是 自动生成的 public 级别的  getter 方法.

自定义 get/set

class Person{

private var myName = "Flink"

def name = this.myName

def name_=(newName : String){     //复写     

myName = newName

println("hi" + myName)

}

}

创建对象:     var   roky = new Person

调用: roky.name  ——>   String = Flink

调用: rocky.name = "Spark" -->   hi : Spark

仅仅暴露 get 方法的两种方式:1>用private val 的方式去定义变量,变量不可更改

2>继续使用 var 方式,使用其他的 set 的具体实现。如下

方式2:def update(newName : String){

如此修改后,就不可以调用 name 的set方法:rocky.name = "hadoop"   错误

rocky.update("hadoop")  -->hi:hadoop

private[this] 对类对象较深层次的访问控制。对象私有,只能被这个对象访问,这个对象的类中的方法也不可以访问。

不仅代表这个方法是类私有,而且还代表了这个类中的方法或者属性是对象私有。

在Person 类中定义方法:  def talk(p:Person) = {

println("hello!!!" +p.name) }

val p1 = nwe Person val p2 = new Person  p1.talk(p2) --> 可以访问

如果 将类改为:private[this] var name = "Flink" ,去掉 myName 变量。在 talk 方法定义时会报错:没有 name 属性。说明 name  不允许被其他对象访问。


类的构造器
注意:所有重载的构造器,都必须首先调用默认的构造器,或者说调用其它重载的构造器

类的构造器:重载
def this(name:String)
{
this() //调用默认的构造器
this.name=name
}

def this(name:String,age:Int){
this(name) //调用其它重载的构造器
this.age=age
}

跟在 class  后的方法即为 默认构造器(即类名)。默认构造器初始化时,会执行所有没有被放在代码块中的代码。

伴生对象 object:其中所有的方法的属性都默认是 static 的。
scala程序中,定义完类之后,一般会定义一个同名的object,它用于存放静态的成员或者方法,当我们第一次调 
用这个伴生对象时,它会执行object 默认的构造方法,只是这个构造方法是不接受参数的,而且这个构造方法只会调用一次,以后不会在调用。
定义:object Person{
println("Scala")
val salary=0.0
def getSalary=salary
}

第一次调用:Person.getSalary 输出: Scala 0.0 第二次调用:只输出 0.0

伴生类和伴生对象在定义的时候必须在同一个文件中。

伴生对象的apply方法:它就是当前类的对象的工厂方法,它可以控制对象的生成。

scala 一般不写 new。 例如: val array = Array(1,2,3) 

实质上是调用Array类的伴生对象的appay方法:val array = Array.apply(1,2,3)

scala不支持多重继成

trait:工具方法的一个容器。类似于接口。可以定义抽象方法。类可以使用extends 关键字继承trait。继承的接口之间使用 with 连接。一般放通用功能。

SparkContext类源码解析:

  SparkContex位于项目的源码路径\spark-master\core\src\main\scala\org\apache\spark\SparkContext.scala中,源文件包含SparkContextClasss声明和其伴生对象SparkContextObject

   class SparkContext extends了Logging。Logging是一个trait,它是用于存放工具方法的一个容器,trait封装方法和字段。把trait混入到类中,就可以重用它们。一个类,可以继承任意多个trait,多个trait继承采用with来实现,可以将trait视为Java的接口interface,跟interface非常相似。唯一的差别在于,interface声明函数,但不实现它们,trait可以实现函数。

trait跟class的差别在于,trait没有任何类参数,trait调用的方法是动态绑定的。

class SparkContext类中有多个重载的构造方法:
如下:
def this(master: String, appName: String, conf: SparkConf) =
this(SparkContext.updatedConf(conf, master, appName))

@deprecated("Passing in preferred locations has no effect at all, see SPARK-10921", "1.6.0")
def this(
master: String,
appName: String,
sparkHome: String = null,
jars: Seq[String] = Nil,
environment: Map[String, String] = Map(),
preferredNodeLocationData: Map[String, Set[SplitInfo]] = Map()) =
{
this(SparkContext.updatedConf(new SparkConf(), master, appName, sparkHome, jars, environment))
if (preferredNodeLocationData.nonEmpty) {
logWarning("Passing in preferred locations has no effect at all, see SPARK-8949")
}
}


val startTime = System.currentTimeMillis()
startTime没有加上private,scala编译时,startTime这个变量是私有的,但会自动的生成它的public的get和set方法,供外部对象调用。

private[spark] val stopped: AtomicBoolean = new AtomicBoolean(false)
private[class_name] 指定可以访问该字段的类,访问的级别较严,在编译时,会自动的生成get和set方法,class_name必须是当前定义的类或类的外部类。

private def assertNotStopped(): Unit = {}
这个方法它是一个过程,因为返回值是Unit,没有结果返回。

 

RDD类源码解析:
class RDD它是个抽象类,

private[spark] def conf = sc.conf
private[class_name] 指定可以访问该字段的类,访问的级别较严,在编译时,会自动的生成get和set方法,class_name必须是当前定义的类或类的外部类。

class RDD类中有很多加了final修饰符的方法,表示:此方法或属性,子类继承此类时不可被覆写,如下:
final def dependencies: Seq[Dependency[_]] = {
checkpointRDD.map(r => List(new OneToOneDependency(r))).getOrElse {
if (dependencies_ == null) {
dependencies_ = getDependencies
}
dependencies_
}
}

final def partitions: Array[Partition] = {
checkpointRDD.map(_.partitions).getOrElse {
if (partitions_ == null) {
partitions_ = getPartitions
}
partitions_
}
}

final def getNumPartitions: Int = partitions.length

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值