Scala 基础 (六):面向对象(下篇)

在之前的文章中总结了Scala面向对象模块基础的内容,接下来学习面向对象的高阶内容。

一、抽象类

==================================================================

如何定义?


// 定义抽象类

abstract class 类名{

	// 定义抽象属性 不赋初始值

	val|var 变量名: 类型

	// 定义抽象方法  只声明,不实现

	def 方法名(): 返回值类型

}



  • 如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需声明为抽象类

  • 重写非抽象方法需要用 override 修饰,重写抽象方法则可以不加 override

  • 子类中调用父类的方法使用 super 关键字

  • 子类对抽象属性进行实现,父类抽象属性可以用 var 修饰;

  • 子类对非抽象属性重写,父类非抽象属性只支持 val 类型,而不支持 var。因为var修饰为可变量,子类继承后可以直接使用修改,没有必要重写。

举个栗子:


// 定义抽象类

abstract class Person{

  // 定义非抽象属性

  val name: String = "person"

  // 抽象属性

  var age: Int



  // 非抽象方法

  def eat(): Unit ={

    println("Person eat")

  }



  // 抽象方法

  def sleep(): Unit

}



class Student extends Person{

  // 实现抽象属性和方法

   var age: Int = 18



   def sleep(): Unit ={

    println("student sleep")

  }



  // 重写非抽象属性和方法

  override val name: String = "Student"



  override def eat(): Unit = {

    super.eat()

    println("Student eat")

  }

}



匿名子类

和 Java 一样,可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类。匿名子类只针对抽象类和接口。

举个栗子:


object Test10_AnnoymousClass {

  def main(args: Array[String]): Unit = {

    // 匿名子类实现

    val person = new Person {

      override var name: String = "alice"



      override def eat(): Unit = println("person eat")

    }



    println(person.name)

    person10.eat()

  }

}



abstract class Person {

  var name: String

  def eat():Unit

}



二、单例对象(伴生对象)

=========================================================================

Scala是一门完全面向对象的语言,没有静态操作。为了能够和Java语言进行交互,使用单例对象来取代static关键字的语义,伴生类的静态声明都可放在伴生对象中。

基本语法:


object 伴生对象名{

	val country: String="China"

}



  • 编译后会生成两个类,伴生对象是伴生类(类名为对应类后加$符号)的单例对象。

  • 单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致,必须在同一个文件中。

  • 单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。

  • Scala 中 obj(arg)的语句实际是在调用该对象的 apply 方法,即 obj.apply(arg)。用以统一面向对象编程和函数式编程的风格。

  • Scala底层对于伴生对象的apply方法进行了优化,调用时可以省略方法名,直接使用单例对象的名称+调用apply方法的参数

  • 当使用 new 关键字构建对象时,调用的其实是类的构造方法,当直接使用类名构建对象时,调用的其实时伴生对象的 apply 方法

举个栗子:


// 伴生类

// 构造器私有化

class Student private(val name: String, val age: Int) {

  def printInfo(): Unit = {

    println(s"Student11: $name $age ${Student11.school}")

  }

}



// 伴生对象

object Student {

  // 看作静态的属性

  val school: String = "清华"

  // 定义类对象实例创建的方法

  def newStudent(name: String,age: Int): Student11 = new Student11(name,age)



  def apply(name: String, age: Int): Student11 = new Student11(name, age)

}



object Test11_Object {

  def main(args: Array[String]): Unit = {

    val student = Student.newStudent("alice", 12)

    student.printInfo()



    val student1 = Student.apply("haha", 12)



    val student2 = Student("lolo", 34)

    student2.printInfo()

  }

}



三、特质

=================================================================

如何定义特质?


trait 特质名 {

	// 代码块

}



  • Scala 语言中,采用特质 trait(特征)来代替接口的概念

  • 多个类具有相同的特征时,就可以将这个特征提取出来,用继承的方式来复用

  • Scala 中的 trait 中即可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入(mixin)多个特质。这种感觉类似于 Java 中的抽象类。

基本语法:


有父类 class extends baseClass with trait1 with trait2 ... {}

没有父类 class extends trait1 with trait2 ... {}



  • 如果一个类在同时继承特质和父类时,应当把父类写在 extends 后。

  • 特质中可以定义抽象和非抽象的属性和方法。

特质叠加引发两种冲突

第一种:一个类(Sub)混入的两个 trait(TraitATraitB)中具有相同的具体方法,且两个 trait 之间没有任何关系

在这里插入图片描述

如果当前父类和特质里面出现了相同的属性和方法,就会起冲突,必须在当前实现的子类(sub)中进行重写。

举个栗子:


class Person {

    val name: String = "Person"

    var age: Int = 18



    def sayHi(): Unit = {

        println(s"hello from : $name")

    }

}



trait Young {

    // abstract and non-abstract attribute

    var age: Int

    val name: String = "young"



    // method

    def play(): Unit = {

        println(s"young people $name is playing")

    }

    def dating(): Unit

}



trait Knowledge {

    var amount: Int = 0

    def increase(): Unit = {

        amount += 1

    }

}



trait Talent {

    def increase(): Unit = {

        println("increase talent")

    }

}



class Student extends Person with Young with Knowledge with Talent{

    override val name: String = "alice"



    def dating(): Unit = {

        println(s"Sutdent $name $age is dating")

    }



    def study(): Unit = println(s"Student $name is studying")



    override def sayHi(): Unit = {

        super.sayHi()

        println(s"hello from : student $name")

    }



    override def increase(): Unit = {

        super.increase() 

        println(s"studnet $name knowledge increase: $amount")

    }

}



object Trait {

    def main(args: Array[String]): Unit = {

        val s = new Student()

        s.sayHi()

        s.increase()



        s.study()

        s.increase()



        s.play()

        s.increase()




# 总结

在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了

![面试真题](https://img-blog.csdnimg.cn/img_convert/c3f3c7e9741adfad8f1f9d4e3c539596.webp?x-oss-process=image/format,png)


![Spring源码笔记](https://img-blog.csdnimg.cn/img_convert/4bd783edf3b1e7ed7d878559b2c4cbe2.webp?x-oss-process=image/format,png)

dge increase: $amount")

    }

}



object Trait {

    def main(args: Array[String]): Unit = {

        val s = new Student()

        s.sayHi()

        s.increase()



        s.study()

        s.increase()



        s.play()

        s.increase()




# 总结

在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了

[外链图片转存中...(img-Ow277Ef4-1714444902927)]


[外链图片转存中...(img-EdRrt8N1-1714444902928)]

> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**
  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值