前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >scala(十二) 特质

scala(十二) 特质

作者头像
用户1483438
发布于 2022-04-18 07:09:24
发布于 2022-04-18 07:09:24
57200
代码可运行
举报
文章被收录于专栏:大数据共享大数据共享
运行总次数:0
代码可运行

特质的定义

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

Scala中的trait中即可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入(mixin)多个特质

Scala引入trait特征,第一可以替代Java的接口,第二个也是对单继承机制的一种补充。

特质的语法

trait 特质名 { trait体 }

案例一:人类有很多不同的特性,有的人会唱歌,有的人会跳舞,也有即会唱歌又会跳舞。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 跳舞
  trait Dancing{
    //具体的舞蹈有子类去实现
    def dance():Unit
  }

  // 唱歌
  trait Sing{
    //具体的歌曲有子类去实现
    def song():Unit
  }

若是把你我他分类的话,那我们都属于人类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 人类
  abstract class Person{

    val name:String

  }

创建学生类;每个学生都会一些基本舞蹈和歌曲,就需要使用 with 去实现 DancingSing两个 特质(trait)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  //学生
  class Student(val na:String) extends Person with Dancing with Sing {
    //重写 姓名属性
    override val name:String=this.na

    override def dance(): Unit = {
      println(s"$name 在跳,广播体操")
    }

    override def song(): Unit = {
      println(s"$name 在唱,保卫黄河")
    }
  
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    val student=new Student("马小跳")
    student.dance() // 马小跳 在跳,广播体操
    student.song() // 马小跳 在唱,保卫黄河
  }

子类需要继承父类的时候,此时extends 关键字用于继承class,特质的实现通过with关键字实现。

案例二:程序员工作离不开电脑,一台电脑组成又分为很多模块。 主板:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait Motherboard{
    def boardInfo():Unit 
  }

CPU:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait CPU{
    def cpuInfo():Unit
  }

内存:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait RAM{
    def ramInfo():Unit
  }

额太多了,就不写了,

定义好电脑的模板

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class Computer(val board:String,val cpu:String,val ram:String) extends Motherboard with CPU with RAM{
    override def boardInfo(): Unit = {
      println(s"主板:$board")
    }

    override def cpuInfo(): Unit = println(s"CPU:$cpu")

    override def ramInfo(): Unit = println(s"内存:$ram")
  }

根据我们的配置,组装电脑

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {

    val   computer=new Computer("超级好的主板","超级好的CPU","超级大的内存")
    
    computer.boardInfo()
    computer.cpuInfo()
    computer.ramInfo()
   
  }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
主板:超级好的主板
CPU:超级好的CPU
内存:超级大的内存

子类不需要继承父class 的时候 ,此时 第一个特质的实现通过 extends 关键字来实现,其他特质依旧使用 with关键字。

通过上面两种案例讲解说明,特质(trait) 的两种实现方式

  1. 子类需要继承父类的时候,此时extends 关键字用于继承class,特质的实现通过with关键字实现。
  2. 子类不需要继承父class 的时候 ,此时 第一个特质的实现通过 extends 关键字来实现,其他特质依旧使用 with关键字。

在特质(trait)中 既可以定义抽象方法,也可以定义具体方法。 如:拿案例二演示(不管合不合理,意思明白就行)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait Motherboard{

    def boardInfo():Unit

    //内存插口
    def ramInterface(): Unit ={
      println("只有两个内存插口")
    }

  }

具体方法,子类可不用重写,直接调用即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    val computer=new Computer("超级好的主板","超级好的CPU","超级大的内存")
    computer.ramInterface()
  }

在特质(trait)中 既可以定义抽象属性,也可以定义具体属性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 主板
  trait Motherboard{
    // 抽象属性
    val info:String
    // 具体属性
    val area=18
    

    def boardInfo():Unit

    //内存插口
    def ramInterface(): Unit ={
      println("只有两个内存插口")
    }

  }

抽象属性需要被子类重写

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class Computer(val board:String,val cpu:String,val ram:String) extends Motherboard with CPU with RAM{
    override def boardInfo(): Unit = println(s"主板:$board")
    override def cpuInfo(): Unit = println(s"CPU:$cpu")
    override def ramInfo(): Unit = println(s"内存:$ram")

    // 重写 Motherboard 中的 info 属性
    override val info: String = "主板"
  }

基本语法:

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

说明

  1. 类和特质的关系:使用继承的关系。
  2. 当一个类去继承特质时,第一个连接词是extends,后面是with。
  3. 如果一个类在继承特质和父类时,应当把父类写在extends后。

对象的混入

这里用上面的案例一 演示说明; 现在的学生,若只会 唱歌跳舞 肯定是不行的,有点家庭比较好的学生肯定还有其他的,。比如:弹钢琴,弹吉他

乐器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait MusicalInstruments{
    def play:Unit
  }

由于该特质(trait)属于个别同学所独有的,所以就无需定义到 Student 中。而是让 使用with关键字,让个别对象去实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    val weh=new Student("王二虎") with  MusicalInstruments {
      override def play(): Unit = {println(s"$name 弹棉花")}
    }
    weh.dance()
    weh.song()
    weh.play()

    val lff=new Student("李菲菲") with  MusicalInstruments {
      override def play(): Unit = {println(s"$name 弹棉花")}
    }

    lff.dance()
    lff.song()
    lff.play()

    val mxt=new Student("马小跳")

    mxt.dance()
    mxt.song()

  }

输出结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
王二虎 在跳,广播体操
王二虎 在唱,保卫黄河
王二虎 弹棉花
李菲菲 在跳,广播体操
李菲菲 在唱,保卫黄河
李菲菲 弹棉花
马小跳 在跳,广播体操
马小跳 在唱,保卫黄河

这种行为就叫对象混入 (2)一个类可以混入(mixin)多个特质 (3)所有的Java接口都可以当做Scala特质使用 (4)动态混入:可灵活的扩展类的功能

方法叠加

由于一个类可以混入(mixin)多个trait,且trait中可以有具体的属性和方法,若混入的特质中具有相同的方法(方法名,参数列表,返回值均相同),必然会出现继承冲突问题。冲突分为以下两种:

第一种,一个类(Sub)混入的两个trait(TraitA,TraitB)中具有相同的具体方法,且两个trait之间没有任何关系,解决这类冲突问题,直接在类(Sub)中重写冲突方法。

第二种,一个类(Sub)混入的两个trait(TraitA,TraitB)中具有相同的具体方法,且两个trait继承自相同的trait(TraitC),及所谓的“钻石问题”,解决这类冲突问题,Scala采用了特质叠加的策略。

所谓的特质叠加,就是将混入的多个trait中的冲突方法叠加起来;

定义五个特质(trait)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait A{
    def sayHello()={
      println("hello","A")
    }
  }

  trait B{

    def sayHello()={
      println("hello","B")
    }
  }

  trait C{

    def sayHello()={
      println("hello","C")
    }
  }

  trait D{

    def sayHello()={
      println("hello","D")
    }
 }

定义 一个 H 类 去实现这些特质(trait)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class H extends A with B with C with D{}

通过 H 调用 sayHello()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    val h =new H
    h.sayHello()

  }

结果报错了;意思是说,这些函数有歧义,不指定该调用谁的 sayHello 函数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Error:(34, 9) class H inherits conflicting members:
  method sayHello in trait C of type ()Unit  and
  method sayHello in trait D of type ()Unit
(Note: this can be resolved by declaring an override in class H.)
  class H extends A with B with C with D{}

也提示你this can be resolved by declaring an override in class H. ;让你重写 sayHello()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class H extends A with B with C with D{

    override def sayHello(): Unit =  println("hello","H")
  }

这样运行就没有问题了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(hello,H)

还有一种情况,子类中可以通过super 访问父类的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class H extends A with B with C with D{
    super.sayHello()
    override def sayHello(): Unit =  println("hello","H")
  }

结果:super.sayHello()打印的是 D 的 sayHello()。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(hello,D)
(hello,H)

这种结果产生的原因很简单,因为的继承顺序是从 A-D,所以从左到右的顺序去找最后一个重名的函数,所以运行的是特质D的sayHello()。

若要调用指定的特质的sayHello(),可以使用[]指定。 如调用 特质B 的sayHello()。 语法:

super[特质名].方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 class H extends A with B with C with D{
    super[B].sayHello()
    override def sayHello(): Unit =  println("hello","H")
  }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(hello,B)
(hello,H)

以上就是第一种冲突方式,及解决方式。

说完第一种,还有第二种,指多个特质(trait)是有联系的。 再定义一个特质(trait) F 并定义一个 sayHello()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait F{
    def sayHello()={
      println("hello","F")
    }
  }

其他特质A-D 继承 F 重写 sayHello(),并各自调用父类(F) 的sayHello()。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trait A extends F {

    override def sayHello()={
      println("hello","A")
      super.sayHello()
    }
  }

  trait B extends F{

    override def sayHello()={
      println("hello","B")
      super.sayHello()
    }
  }

  trait C extends F{

    override def sayHello()={
      println("hello","C")
      super.sayHello()
    }
  }

  trait D extends F{

    override def sayHello()={
      println("hello","D")
      super.sayHello()
    }
  }

H 不变

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class H extends A with B with C with D{
    super.sayHello()
    override def sayHello(): Unit =  println("hello","H")
  }

此时的运行结果如何?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    val h =new H
    h.sayHello()
  }

结果:这种就是所谓的“钻石问题”

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(hello,D)
(hello,C)
(hello,B)
(hello,A)
(hello,F)
(hello,H)

原理也很简单。 首先运行的是H,H调用spuer 会运行特质D,然后由D调用 super ,此时D并不是调用 F,而是指向的是上一个特质C ,然后C又指向B,B又指向A,此时A才真正的指向F。由于A-D super 是在打印下面所有先这执行的打印后执行的super。H和其他相反,super在前,打印在后。运行最后运行的是H。

钻石的形式
钻石的形式

红色:表示继承或实现 黑色:表示指向

自身类型

有这么一个需求,需要将对象持久化(保存到磁盘) 回顾 java 实现对象持久化步骤

  1. 实现 Serializable 接口
  2. 提供get/set 方法
  3. 序列化,使用ObjectOutputStream 对对象写入文件
  4. 反序列化,读取文件生成对象,使用ObjectInputStream

scala 中也是也是如此 创建一个Person类,提供get/set 方法,暂时不指定 Serializable 接口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class Person {
    // id
    @BeanProperty var id:Int=_
    // 姓名
    @BeanProperty var name:String=_
    // 年龄
    @BeanProperty var age:Int=_
  }

序列化、反序列化是一个完整的功能,我们可以将其封装到单独的类中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class ObjectWriteAndRead{
    /**
     * 序列化
     * @param path 文件地址
     */
    def write(path:String): Unit ={
      try {
        val fos=new FileOutputStream(path)
        val objectInput=new ObjectOutputStream(fos)
        // 写入磁盘
       objectStream.writeObject(this)

        // 刷新与关闭
        objectStream.flush()
        objectStream.close()
        fos.close()
        println("序列化成功")
      }catch {
        case e:IOException=>{
          println("序列化失败",e)
        }
      }
    }
  }

Person 若要进行序列化或反序列化可以继承该类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 class Person  extends ObjectWriteAndRead{...}

若对象没有实现序列化接口,运行时肯定会报错

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def main(args: Array[String]): Unit = {
    //创建对象
    val person=new Person()
    person.setId(1001)
    person.setName("王小二")
    person.setAge(19)

    person.write("D:\\aaa.txt")
  }

报错

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(序列化失败,java.io.NotSerializableException: com.admin.xxx.traita.Demo03$Person)

别觉得我说的是废话,遇到这种情况,我们很多时候都会忘记(是否实现了Serializable接口),只有等到运行报错时,翻看异常信息才恍然大悟。有没有一种机制能让我们在一开始就提示我们,而不是等到出问题之后?

这就需要自身类型了,它主要用于提醒子类,子类继承父类,需要满足继承父类的某些条件。如:必须实现 Serializable接口

语法:

this:类型 =>

案例:指定 ObjectWriteAndRead 的自身类型

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class ObjectWriteAndRead{
    this: Serializable =>
    ...
  }

此时 Person 类就弹错误,告知其需要实现 Serializable 接口。

自身类型
自身类型

按照提示实现 Serializable 接口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Person  extends ObjectWriteAndRead with Serializable {...}

然后再运行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
序列化成功

这就是自身类型的作用,说重要也不重要,但是是一个很好的辅助,大大提高我们开发效率,毕竟减少了解决报错的时间。

最后也把反序列化完成吧,在ObjectWriteAndRead新增一个read函数,用于进行反序列化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 class ObjectWriteAndRead{
    this: Serializable =>
    /**
     * 序列化
     * @param path 文件地址
     */
    def write(path:String): Unit ={
      try {
        val fos=new FileOutputStream(path)
        val objectStream=new ObjectOutputStream(fos)
        // 写入磁盘
        objectStream.writeObject(this)

        // 刷新与关闭
        objectStream.flush()
        objectStream.close()
        fos.close()
        println("序列化成功")
      }catch {
        case e:IOException=>{
          println("序列化失败",e)
        }
      }
    }

    /**
     * 反序列化
     * @param path
     * @return
     */
    def read(path:String):AnyRef={

     try {
       val fis=new FileInputStream(path)

       val objectStream=new ObjectInputStream(fis)
       println("反序列化成功")
       objectStream.readObject()
     }catch {
       case e:IOException =>{
         println("反序列化失败",e)
         null
       }
     }
    }
  }

运行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    //创建对象
    val person=new Person()
    person.setId(1001)
    person.setName("王小二")
    person.setAge(19)
    // 序列化
    person.write("D:\\aaa.txt")

    //反序列化
    val newPerson = person.read("D:\\aaa.txt").asInstanceOf[Person]
    println(person.getId)
    println(person.getName)
    println(person.getAge)
  }

person.read("D:\aaa.txt") : 是一个反序列化的结果,类型是AnyRef .asInstanceOf[T] 用于类型强转

输出结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
序列化成功
反序列化成功
1001
王小二
19

完整代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Person  extends ObjectWriteAndRead with Serializable {
    // id
    @BeanProperty var id:Int=_
    // 姓名
    @BeanProperty var name:String=_
    // 年龄
    @BeanProperty var age:Int=_

  }

  def main(args: Array[String]): Unit = {
    //创建对象
    val person=new Person()
    person.setId(1001)
    person.setName("王小二")
    person.setAge(19)
    // 序列化
    person.write("D:\\aaa.txt")



    //反序列化
    val newPerson = person.read("D:\\aaa.txt").asInstanceOf[Person]
    println(person.getId)
    println(person.getName)
    println(person.getAge)

  }


  class ObjectWriteAndRead{
    this: Serializable =>
    /**
     * 序列化
     * @param path 文件地址
     */
    def write(path:String): Unit ={
      try {
        val fos=new FileOutputStream(path)
        val objectStream=new ObjectOutputStream(fos)
        // 写入磁盘
        objectStream.writeObject(this)

        // 刷新与关闭
        objectStream.flush()
        objectStream.close()
        fos.close()
        println("序列化成功")
      }catch {
        case e:IOException=>{
          println("序列化失败",e)
        }
      }
    }

    /**
     * 反序列化
     * @param path
     * @return
     */
    def read(path:String):AnyRef={

     try {
       val fis=new FileInputStream(path)

       val objectStream=new ObjectInputStream(fis)
       println("反序列化成功")
       objectStream.readObject()
     }catch {
       case e:IOException =>{
         println("反序列化失败",e)
         null
       }
     }
    }
  }

扩展

类型检查和转换

定义三个类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  class Person{
    val name="Person"
  }

  class Student extends Person{
    override val name: String = "Student"
  }

  class Teacher extends Person{
    override val name: String = "Teacher"
  }

Student 与 Teacher 都继承 Person

  1. obj.isInstanceOf[T]:判断obj是不是T类型。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    val stu:Person=new Student

    println(s"判断是否为 Student 类:${stu.isInstanceOf[Student]}")
    println(s"判断是否为 Teacher 类:${stu.isInstanceOf[Teacher]}")
  }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
判断是否为 Student 类:true
判断是否为 Teacher 类:false
  1. obj.asInstanceOf[T]:将obj强转成T类型。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {
    val stu:Person=new Student

    val o1=stu.asInstanceOf[Person]
    println("o1:"+o1.name)

    val o2=stu.asInstanceOf[Student]
    println("o2:"+o2.name)

    val o3=stu.asInstanceOf[Teacher]
    println("o3:"+o3.name)

  }

o3 无法转换 无法转换为 Teacher

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
o1:Student
o2:Student
Exception in thread "main" java.lang.ClassCastException: com.admin.xxx.traita.Demo04$Student cannot be cast to com.admin.xxx.traita.Demo04$Teacher

至于为啥o1 输出的也是 Student 因为Scala 中属性也具有多态性。

  1. classOf获取对象的类名。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  def main(args: Array[String]): Unit = {

    val clazz: Class[Student] = classOf[Student]
    println(clazz.getSimpleName) // 获取类名
  }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Student

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
2021年大数据常用语言Scala(三十一):scala面向对象 特质(trait)
1. trait 中可以有 抽象的 也可以有 具体的 2. 一个类可以实现多个trait(通过with关键字) 3. 单个对象也可以附件多个trait 4. trait本身也可以继承其它class 通过这3个特性,我们可以体现出来。trait是一种 代码复用的最小单元 我们可以将想要的特性功能封装到trait中 不管是让class去附加 还是单个对象去附加 都OK 同时附加的数量不受到影响。
Lansonli
2021/10/11
3980
Scala 基础 (六):面向对象(下篇)
在之前的文章中总结了Scala面向对象模块基础的内容,接下来学习面向对象的高阶内容。
百思不得小赵
2022/12/01
5350
Scala 基础 (六):面向对象(下篇)
带你快速掌握Scala操作———(5)
类继承了多个trait后,可以依次调用多个trait中的同一个方法,只要让多个trait中的同一个方法在最后都依次执行super关键字即可。类中调用多个tait中都有这个方法时,首先会从最右边的trait方法开始执行,然后依次往左执行,形成一个调用链条。
刘浩的BigDataPath
2021/04/13
5530
带你快速掌握Scala操作———(5)
02.Scala:面向对象、Object、抽象类、内部类、特质Trait
scala是支持面向对象的,也有类和对象的概念。我们依然可以基于scala语言来开发面向对象的应用程序。
Maynor
2021/04/09
1.3K0
Scala 【 9 Trait 】
​ 可以将 Trait 作为接口来使用,此时的 Triat 就与 Java 中的接口非常类似。
Lokinli
2023/03/09
2430
Scala学习教程笔记二之函数式编程、Object对象、伴生对象、继承、Trait、
1:Scala之函数式编程学习笔记: 1:Scala函数式编程学习: 1.1:Scala定义一个简单的类,包含field以及方法,创建类的对象,并且调用其方法: class User { private var name = "张三"; def hello(): Unit ={ println("hello : " + name) } //注:如果定义方法
别先生
2018/04/02
1.2K0
Scala 【 8 面向对象编程 - 继承 】
继承就代表,子类可以从父类继承父类的 field 和 method 。子类可以在自己内部放入父类所没有的子类特有的 field 和 method 。
Lokinli
2023/03/09
4010
大数据利器--Scala语言学习(基础)
在 Scala 当中,函数是一等公民,像变量一样,既可以作为函数的参数使用,也可以将函数赋值给一个变量. ,函数的创建不用依赖于类或者对象,而在 Java 当中,函数的创建则要依赖于类、抽象类或者接口。
MiChong
2020/09/24
1.1K0
大数据利器--Scala语言学习(基础)
Spark基础-scala学习(二、面向对象)
面向对象编程之类 //定义一个简单的类 scala> :paste // Entering paste mode (ctrl-D to finish) //类默认public的 class HelloWorld{ private var name = "leo" def sayHello(){print("Hello,"+name)} def getName = name } // Exiting paste mode, now interpreting. defined class Hel
老梁
2019/09/10
7150
scala(九) 封装、继承与多态
封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。 java封装操作如下:
用户1483438
2022/04/14
7290
Scala 学习之面向对象(3)
        ---> 伴生类和伴生对象    object 相当于 Java 中的 static
py3study
2020/01/07
3420
Spark基础-scala学习(三、Trait)
面向对象编程之Trait trait基础知识 将trait作为接口使用 在trait中定义具体方法 在trait中定义具体字段 在trait中定义抽象字段 trait高级知识 为实例对象混入trait trait调用链 在trait中覆盖抽象方法 混合使用trait的具体方法和抽象方法 trait的构造机制 trati字段的初始化 让trait继承类 将trait作为接口使用 trait作为接口,和java中的接口非常类似 在triat中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出方法的具体实现
老梁
2019/09/10
5450
Scala trait特质 深入理解
在Scala中,trait(特质)关键字有着举足轻重的作用。就像在Java中一样,我们只能在Scala中通过extends进行单一继承,但trait可以让我们从语义上实现了多重继承。通过对继承的类混入(mixin)多个特质,来达到多重继承的目的。乍一看,trait和Java中的interface接口很像,但是,细节上它们又有着大不同。
w4ngzhen
2023/10/16
4060
Scala trait特质 深入理解
原 荐 Scala的面向对象
----------目录--------------------------------------------------------- 1.Scala简介和安装 2.Scala语法介绍 3.Scala的函数 4.Scala中的集合类型 5.Scala的面向对象 ------------------------------------------------------------------------------------------------------------- Scala的面向对象 一、
云飞扬
2018/05/07
9090
原                    荐                                                            Scala的面向对象
大数据技术之_16_Scala学习_05_面向对象编程-中级
1、scala 进行 package 打包时,可以有如下形式。【案例演示+反编译查看】
黑泽君
2019/04/01
1.3K0
大数据技术之_16_Scala学习_05_面向对象编程-中级
scala快速入门系列【特质】
本篇作为scala快速入门系列的第二十六篇博客,为大家带来的是关于特质(trait)的内容。
大数据梦想家
2021/01/26
5090
scala快速入门系列【特质】
【建议收藏】|3分钟让你学会Scala Trait 使用
Scala 是一种强大的静态类型编程语言,其中的 Trait 是一种重要的特性。Trait 可以被看作是一种包含方法和字段定义的模板,可以被其他类或 Trait 继承或混入。在本文中,我们将介绍 Scala Trait 的边界(Boundary)的概念,并展示如何使用它来限制 Trait 的使用范围。
857技术社区
2023/07/26
2990
【建议收藏】|3分钟让你学会Scala Trait 使用
2021年大数据常用语言Scala(三十):scala面向对象 继承(extends)
scala和Java一样,使用extends关键字来实现继承。可以在子类中定义父类中没有的字段和方法,或者重写父类的方法。
Lansonli
2021/10/11
5570
大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值
  设计一个 var total Int 表示总人数,我们在创建一个小孩时,就把 total 加1,并且 total 是所有对象共享的就 ok 了。我们使用伴生对象来解决。 示例代码如下:
黑泽君
2019/04/01
1.5K0
大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值
Scala入门之面向对象
scala> type S = String defined type alias S
算法之名
2019/08/20
3320
相关推荐
2021年大数据常用语言Scala(三十一):scala面向对象 特质(trait)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档