Spark零基础实战 第2章 Scala面向对象彻底精通

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/myvanguard/article/details/86618714

第2章 Scala面向对象彻底精通

对象、类、特质(Trait)用来定义Scala的API和库,它们是Scala为面向对象编程提供的基础机制。Scala面向对象涉及的重要概念有class、object、构造器、字段、方法、抽象类、接口等,这些概念很多跟Java面向对象中的概念相似,但也有一些Scala独特之处。

2.1 Scala面向对象详解

2.1.1Scala中的class、object初介绍

在Scala中,类名不是必须和文件名相同且一个文件中可以定义多个class。
同时Scala的class中不存在静态成员,Java中的静态成员由Scala中的object对象替代,当object对象名和class名相同时则称object为class的伴生对象。
Scala类定义语法:

class ClassName{

}

关键字class是Scala中所有类定义的必须修饰符,包含普通类、抽象类、样例类等。

object定义的对象为单例对象。对于同名的object和class对象互称为伴生对象和伴生类,伴生对象和伴生类必须在同一个文件中。

class HiScala {
//一个私有的name属性和两个方法
    private val name:String = "zhangsan"
    def sayName(): Unit ={
        println(name)
    }
    def getName = name
}
object HiScala{
    def main(args: Array[String]): Unit = {
        val hiScala = new HiScala
        hiScala.sayName
        val tmp = hiScala.getName
        println(tmp)
    }
}

object本身有默认的constructor,这个constructor只会被调用一次。

注意:
①伴生类和伴生对象一定要在同一个文件中;
②伴生对象可以访问伴生类的私有成员。

Scala 是单继承多立现的(用 with 关键字混人多个特质)
子类不能重写父类中被final修饰的方法和属性

abstract class Animal {
    //子类不能重写父类中被final修饰的方法和属性
    final val sex: String = "obj"

    final def sayHi = {
        println("Hi Scala")
    }

    def eat = {
        println("Eat food!!!")
    }

    def run
}

class Cat extends Animal {

    override def eat: Unit = {
        println("Cat eating")
    }

    override def run: Unit = {
        println("Cat Running")
    }
}

class Dog extends Animal {
    override def run: Unit = {
        println("Dog is running")
    }
}

object AnimalTest {
    def main(args: Array[String]): Unit = {
        val c = new Cat
        c.eat
        c.run
        val d = new Dog
        d.eat
        d.run
    }
}

2.1.2主构造器与辅助构造器

Scala默认构造器在类上,重载构造器,第一行必须是默认构造器或者其他构造器。

//默认无参构造器class Person{}
// 默认带一个或者多个参数的构造器
class Person(name: String) {
    println(this.name)

    //构造器重载 第一行必须是默认构造器
    def this(name: String, age: Int) {
        this(name)
        println(name + " " + age)
    }

    def this(name: String, age: Int, sex: String) {
        this(name, age)
        println(name + " " + age)
    }
}

object Person {
    def main(args: Array[String]): Unit = {
        //创建实例必须传入指定的参数
        val s = new Person("name")
        println(s)
    }
}

2.1.3类的字段和方法彻底精通

var类型的属性Scala会帮助生成public的getter和setter方法;
val类型属性因为不可变,所以只有getter方法。
如果显示定义成private类型属性,Scala会生成私有的对应的getter和setter方法,外界无法访问。
Scala默认的方法是public的,
若在方法的前面加上private,则对象实例无法访问该方法。
若定义无参方法时不带括号,则调用时也不能写
如果字段或者方法被private[this]修饰,则该字段或方法只能被当前对象访问,当前对象的其他实例无法访问。

class Student {
    /**
      * var 属性会生成public的setter/getter方法
      * val 属性只有getter方法
      * private var属性会生成私有的setter/getter方法 外界无法访问
      *
      * 方法默认是public
      * private方法 对象的实例无法访问该方法
      */
    var name:String = "zhangsan"
    var age = 30
    val sex = "female"
    private var myName = "Flink"
    def sayHi = println("Hi!!!")
    def increase(age:Int):Int=this.age+age
    def myNames = this.myName
    //复写setter方法
    def myName_ (newName:String): Unit ={
        myName = newName
        println("Hi"+myName)
    }
    //自定义setter方法
    def update(newName:String): Unit ={
        myName = newName
        println("Hi:"+myName)
    }

    //使用private [this]修饰 该字段或者方法只能被当前对象访问 当前对象的其他实例无法访问
    private[this] val a = "Hello"
    private[this] def test(): Unit ={
        println("Testing")
    }



}
object Student{
    def main(args: Array[String]): Unit = {
        val s = new Student
        s.name
        s.name = "lisi"
        s.sex
    }
}

2.1.4抽象类、接口的实战详解

将有abstract关键字的类称为抽象类。
抽象类中的字段不能显示用abstract
子类可以访问父类的非私有属性
抽象变量val和var定义,若一个类中定义了抽象成员(变量和方法),则该类必须定义为抽象类。
子类继承父类必须实现父类的抽象方法

abstract class P(name: String) {
    println(this.name)
    private var age = 20
    //抽象类中的字段不能显示用abstract
    //Student可以访问父类的非私有属性
    val sex:String = "male"
}
class Student extends P("lilei"){
    def main(args: Array[String]): Unit = {
        val student = new Student
        student.sex
    }
}
abstract class AbstractTest{
    val str:String
    val strImpl:String="zhangsan"
    val integer:Int
    var bool:Boolean
    def add(a:Int,b:Int):Int
    def multi(x:Int,y:Int):Int={
        x*y
    }
}
/*继承抽象类,必须实现抽象类中未实现的成员*/
class AbstractTest1 extends AbstractTest{
    override val str: String =  "a"
    override val strImpl: String = "b"
    override val integer: Int = 1

    override var bool: Boolean = false

    override def add(a: Int, b: Int): Int = {
        2+2
    }

    override def multi(x: Int, y: Int): Int = {
        3+5
    }
}

Scala的特质相当于Java中的接口,不过特质中可以有实现的方法
在Scala中实现特质被称为混入,混入的第一个特质用关键字extends,
混入更多的特质用with关键字。
当子类混入这两个(或者多个)特质的相同字段时,需要重写该字段

trait PersonTrait {
    val name:String
    val age = 30
    def eat(str:String)={
        println(str)
    }

}
trait WorkerTrait{
    val age=25
    def work: Unit ={
        println("working")
    }
}
class ClassStudent extends WorkerTrait with PersonTrait{
    val name:String = "zhangsan"
    //当子类混入这两个特质的相同字段时,需要重写该字段
    override val age = 15
}
object Test{
    def main(args: Array[String]): Unit = {
        val s = new ClassStudent
        println(s.eat("eating"))
        println(s.work)
        println(s.age)
    }
}

2.1.5 Scala Option类详解

Scala的Option[T]是容器对于给定的类型的零个或一个元件。Option[T]可以是一些
[T]或None对象,它代表一个缺失值。
对比null值Java可用这表明没有任何值。

object OptionTest {

    def main(args: Array[String]): Unit = {
        val capital = Map("China"->"Peking","France"->"Paris")
        println(capital.get("China"))
        println(capital.get("India"))//当找不到时返回结果None
    }
}

2.1.6 object的提取器

object中提供了apply方法。apply的作用是在创建对象的时候不直接用new,而是直接用对象加参数,这时调用了伴生对象的apply方法。

注意:对于抽象类也是可以直接调用伴生对象的apply方法。它的具体工作原理是先调用其伴生对象的apply方法,在这个方法中调用的是抽象类的子类的伴生对象的apply方法。

object ExtractorTest {

    def main(args: Array[String]): Unit = {
        println("Apply method" + apply("Zara", "gmail.com"))
        println("UnApply method" + unapply("[email protected]"))
        println("UnApply method" + unapply("Zara Ali"))

    }

    //注入
    def apply(user: String, domain: String) = {
        user + "@" + domain
    }

    //unapply 提取器
    def unapply(str: String): Option[(String, String)] = {
        val parts = str.split("@")
        if (parts.length == 2) {
            Some(parts(0), parts(1))
        } else {
            None
        }
    }

}

2.1.7Scala的样例类实战详解

样例类很简单也很重要,与后面的模式匹配结合使用。

样例类定义:
case class Person//类似于抽象类,只是关键字为case。
注意:样例类不能继承样例类。

abstract class Amount
//继承了普通类的2个样例类
case class Dollar(value:Double)extends Amount
case class Currency(value:Double,unit:String) extends Amount
//样例对象
case object Nothing extends Amount

猜你喜欢

转载自blog.csdn.net/myvanguard/article/details/86618714