scala语言基础:面向对象编程中的继承与特质

scala和Java、Python一样是面向对象语言,本文讲解scala面向对象中继承与特质的相关概念与实例。

5868a7ccf4ec87da1211d435a6ce2991.png

1.继承

Scala中的继承与Java有着显著的不同:
(1)重写一个非抽象方法必须使用override修饰符。
(2)只有主构造器可以调用超类的主构造器。
(3)在子类中重写超类的抽象方法时,不需要使用override关键字。
(4)可以重写超类中的字段。
Scala和Java一样,不允许类从多个超类继承,因此,下面我们只讨论继承自一个类的情形。

抽象类

以汽车为例子,首先我们创建一个抽象类,让这个抽象类被其他类继承。

abstract class Car{   //是抽象类,不能直接被实例化
   val carBrand: String //字段没有初始化值,就是一个抽象字段
     def info() //抽象方法,不需要使用abstract关键字
     def greeting() {println("Welcome to my car!")}
}

关于上面的定义,说明几点:
(1)定义一个抽象类,需要使用关键字abstract。
(2)定义一个抽象类的抽象方法,也不需要关键字abstract,只要把方法体空着,不写方法体就可以。
(3)抽象类中定义的字段,只要没有给出初始化值,就表示是一个抽象字段,但是,抽象字段必须要声明类型,比如:val carBrand: String,就把carBrand声明为字符串类型,这个时候,不能省略类型,否则编译会报错。

扩展类

抽象类不能直接被实例化,所以,下面我们定义几个扩展类,它们都是扩展了Car类,或者说继承自Car类。

class BMWCar extends Car {
    override val carBrand = "BMW"  //重写超类字段,需要使用override关键字,否则编译会报错
    def info() {printf("This is a %s car. It is on sale", carBrand)} //重写超类的抽象方法时,不需要使用override关键字,不过,如果加上override编译也不错报错
    override def greeting() {println("Welcome to my BMW car!")} //重写超类的非抽象方法,必须使用override关键字
}

class BYDCar extends Car { 
    override val carBrand = "BYD" //重写超类字段,需要使用override关键字,否则编译会报错
    def info() {printf("This is a %s car. It is cheap.", carBrand)} //重写超类的抽象方法时,不需要使用override关键字,不过,如果加上override编译也不错报错
    override def greeting() {println("Welcome to my BYD car!")} //重写超类的非抽象方法,必须使用override关键字
}

2.特质

Java中提供了接口,允许一个类实现任意数量的接口。在Scala中没有接口的概念,而是提供了“特质(trait)”,它不仅实现了接口的功能,还具备了很多其他的特性。Scala的特质,是代码重用的基本单元,可以同时拥有抽象方法和具体方法。Scala中,一个类只能继承自一个超类,却可以实现多个特质,从而重用特质中的方法和字段,实现了多重继承。

定义

特质的定义和类的定义非常相似,有区别的是,特质定义使用关键字trait。

trait CarId{
  var id: Int
    def currentId(): Int     //定义了一个抽象方法
}

上面定义了一个特质,里面包含一个抽象字段id和抽象方法currentId。注意,抽象方法不需要使用abstract关键字,特质中没有方法体的方法,默认就是抽象方法。

把特质混入类中

特质定义好以后,就可以使用extends或with关键字把特质混入类中。

class BYDCarId extends CarId{ //使用extends关键字
   override var id = 10000 //BYD汽车编号从10000开始
     def currentId(): Int = {id += 1; id} //返回汽车编号
 }
 class BMWCarId extends CarId{ //使用extends关键字
   override var id = 20000 //BMW汽车编号从20000开始
     def currentId(): Int = {id += 1; id} //返回汽车编号
 }

包含具体实现

上面的实例中,特质只包含了抽象字段和抽象方法,相当于实现了类似Java接口的功能。实际上,特质也可以包含具体实现,也就是说,特质中的字段和方法不一定要是抽象的。

trait CarGreeting{
  def greeting(msg: String) {println(msg)}  
}

CarGreeting会把欢迎信息打印出来。

把多个特质混入类中

上面我们已经定义了两个特质,即CarId和CarGreeting。现在,我们可以把两个特质都混入到类中。
请登录Linux系统,进入shell命令提示符状态,然后,输入以下命令进入“/usr/local/scala/mycode”目录,打开vim编辑器:

trait CarId{
  var id: Int
    def currentId(): Int     //定义了一个抽象方法
}
trait CarGreeting{
  def greeting(msg: String) {println(msg)}  
}

class BYDCarId extends CarId with CarGreeting{ //使用extends关键字混入第1个特质,后面可以反复使用with关键字混入更多特质
   override var id = 10000 //BYD汽车编号从10000开始
     def currentId(): Int = {id += 1; id} //返回汽车编号
 }
 class BMWCarId extends CarId with CarGreeting{ //使用extends关键字混入第1个特质,后面可以反复使用with关键字混入更多特质
   override var id = 20000 //BMW汽车编号从10000开始
     def currentId(): Int = {id += 1; id} //返回汽车编号
 } 
 object MyCar { 
    def main(args: Array[String]){
        val myCarId1 = new BYDCarId()       
        val myCarId2 = new BMWCarId()
        myCarId1.greeting("Welcome my first car.")
        printf("My first CarId is %d.\n",myCarId1.currentId)        
        myCarId2.greeting("Welcome my second car.")
        printf("My second CarId is %d.\n",myCarId2.currentId)
    }
}

上面命令执行后,会在屏幕输出以下结果:

Welcome my first car.
My first CarId is 10001.
Welcome my second car.
My second CarId is 20001.

参考链接:

http://dblab.xmu.edu.cn/blog/spark/

https://www.runoob.com/scala/scala-tutorial.html

3fc63e6e2dd0e25f071bad223521ab02.png

历史推荐

妈妈再也不用担心双系统安装了!

Spark机器学习:模型评估指标

Spark机器学习:频繁模式挖掘

爬虫实战:Selenium爬取京东商品

爬虫实战:豆瓣电影top250爬取

爬虫实战:Scrapy框架爬取QQ音乐

282b52871ccd173f1f5899f6fbd36e95.png

数据分析与挖掘

数据结构与算法

机器学习与大数据组件

欢迎关注,感谢“在看”,随缘稀罕~

976e705167c4496fedd40046a2770a55.jpeg 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值