Scala特证/特质【6.7 特质(Trait)】

Scala特证/特质【6.7 特质(Trait)】

    • 6.7 特质(Trait)
    • Java 的接口
      • 接口的作用
      • 抽象类的作用
    • 6.7.1 特质声明
    • 6.7.2 特质基本语法
    • 6.7.3 特质叠加
    • 6.7.4 特质叠加执行顺序
    • 6.7.5 特质自身类型
    • 6.7.6 特质和抽象类的区别

(任意内容)

此处输入任意想输入的内容

6.7 特质(Trait)

  • Scala 语言中,采用特质 trait(特征)来代替接口的概念 ,也就是说,多个类具有相同的特质(特征)时,就可以将这个特质(特征)独立出来,采用关键字 trait 声明。
  • Scala 中的 trait 中即可以有抽象属性和方法,也可以有具体的属性和方法,一个类可
    以混入(mixin)多个特质。这种感觉类似于 Java 中的抽象类。
  • Scala 引入 trait 特征,第一可以替代 Java 的接口,第二个也是对单继承机制的一种
    补充。

Java 的接口

Java中的接口(Interface)是一种抽象类型,用于定义类应该具有的行为。接口可以看作是一组方法的集合,但是接口不能包含实现代码,只能定义方法的签名。类可以实现一个或多个接口,并提供接口中定义的方法的具体实现。

接口的定义使用interface关键字,语法如下:

public interface MyInterface {// 抽象方法void abstractMethod();// 默认方法default void defaultMethod() {// 方法实现}// 静态方法static void staticMethod() {// 方法实现}
}

在Java中,类通过implements关键字来实现接口:

public class MyClass implements MyInterface {// 实现接口中的抽象方法public void abstractMethod() {// 方法实现}
}

一个类可以实现多个接口,通过逗号分隔:

public class MyClass implements Interface1, Interface2 {// 实现接口中的抽象方法// ...
}

接口的作用

接口中的方法可以是抽象方法、默认方法(默认实现)和静态方法。抽象方法由实现类提供具体实现,而默认方法和静态方法可以直接在接口中提供实现代码。默认方法可以被实现类重写,静态方法则不能。

接口在Java中用于实现多态性和代码复用,它提供了一种契约机制,用于定义类的行为规范。通过实现接口,可以在不同的类中共享一组方法,提高代码的灵活性和可扩展性。接口在Java中被广泛应用于各种编程场景,例如回调机制、事件处理、依赖注入等。

接口在编程中起到了以下几个重要的作用:

  1. 定义契约:接口定义了一组方法的契约或规范,指定了类应该具备的行为。通过接口,可以明确地定义类应该提供哪些方法,以及这些方法应该如何被实现。接口提供了一种契约机制,帮助程序员在不同的类之间建立统一的行为规范。

  2. 实现多态:接口是实现多态性的关键。通过接口,可以实现类的多态性,使得不同的对象可以以统一的方式对待。通过接口的引用,可以引用不同实现类的对象,并调用它们实现的接口方法,实现了代码的灵活性和可扩展性。

  3. 代码复用:接口提供了一种代码复用的机制。通过接口,可以定义一组方法,并在多个类中实现这些方法。其他类可以实现相同的接口,从而复用接口中定义的方法。这种方式可以减少代码的重复编写,提高代码的可维护性和可复用性。

  4. 解耦和组件化:接口可以帮助解耦和实现组件化。通过接口,不同的模块或组件之间可以通过接口进行通信,而不需要了解具体的实现细节。这样可以降低模块之间的耦合度,提高系统的灵活性和可扩展性。

  5. 定义规范:接口可以被用作定义规范的工具。通过接口,可以定义一组方法和常量,并约束其他类去实现这些方法或使用这些常量。这样可以保证代码的一致性和可靠性。

总而言之,接口在编程中具有重要的作用,它定义了类的行为规范、实现多态性、实现代码复用、解耦和组件化,以及定义规范等。通过接口,可以提高代码的灵活性、可维护性和可扩展性,使得程序更加可靠和可重用。

抽象类的作用

抽象类在面向对象编程中起着重要的作用,它具有以下几个主要作用:

  1. 定义通用行为:抽象类可以定义一组通用的方法和属性,这些方法和属性可以被其子类继承和重写。抽象类可以提供一种通用的行为规范,让子类按照自己的需求进行具体实现。

  2. 实现代码复用:抽象类可以包含一些通用的方法的实现,这样子类就可以直接继承这些方法的实现,避免了代码的重复编写。通过抽象类的继承关系,可以实现代码的复用,提高代码的可维护性和可复用性。

  3. 实现多态性:抽象类可以作为父类,被其子类进行继承和扩展。通过抽象类的引用,可以引用不同子类的对象,实现多态性。这样可以在运行时根据实际对象的类型调用相应的方法,实现灵活的代码结构。

  4. 定义抽象方法:抽象类可以定义抽象方法,这些方法只有方法的声明而没有具体的实现。抽象方法必须由子类进行具体实现,通过抽象方法的定义,可以强制子类去实现特定的行为。

  5. 作为模板类:抽象类可以作为模板类,定义一些通用的方法和属性,提供给子类进行继承和使用。子类可以通过继承抽象类,并根据自己的需求进行具体实现和扩展,从而达到代码复用和模块化的目的。

总而言之,抽象类在面向对象编程中具有重要作用,它可以定义通用行为、实现代码复用、实现多态性、定义抽象方法和作为模板类。通过抽象类,可以提高代码的可维护性、可复用性和可扩展性,使得程序设计更加灵活和可靠。

6.7.1 特质声明

1)基本语法

trait 特质名 {trait 主体
}

2)案例实操

trait PersonTrait {// 声明属性var name:String = _// 声明方法def eat():Unit={}// 抽象属性var age:Int// 抽象方法def say():Unit
}
通过查看字节码,可以看到特质=抽象类+接口

6.7.2 特质基本语法

  • 一个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了 extends 关键字,如果有多个特质或存在父类,那么需要采用 with关键字连接。
    在这里插入图片描述
    2)说明
    (1)类和特质的关系:使用继承的关系。
    (2)当一个类去继承特质时,第一个连接词是 extends,后面是 with。
    (3)如果一个类在同时继承特质和父类时,应当把父类写在 extends 后。

3)案例实操
(1)特质可以同时拥有抽象方法和具体方法
(2)一个类可以混入(mixin)多个特质
(3)所有的 Java 接口都可以当做 Scala 特质使用
(4)动态混入:可灵活的扩展类的功能

  • (4.1)动态混入:创建对象时混入 trait,而无需使类混入该 trait
  • (4.2)如果混入的 trait 中有未实现的方法,则需要实现
trait PersonTrait {//(1)特质可以同时拥有抽象方法和具体方法// 声明属性var name: String = _// 抽象属性var age: Int// 声明方法def eat(): Unit = {println("eat")}// 抽象方法def say(): Unit}
trait SexTrait {var sex: String
}
//(2)一个类可以实现/继承多个特质
//(3)所有的 Java 接口都可以当做 Scala 特质使用
class Teacher extends PersonTrait with java.io.Serializable {override def say(): Unit = {println("say")}override var age: Int = _}
object TestTrait {def main(args: Array[String]): Unit = {val teacher = new Teacherteacher.say()teacher.eat()//(4)动态混入:可灵活的扩展类的功能val t2 = new Teacher with SexTrait {override var sex: String = "男"}//调用混入 trait 的属性println(t2.sex)}
}

6.7.3 特质叠加

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

冲突分为以下两种:

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

  • 第二种,一个类(Sub)混入的两个 trait(TraitA,TraitB)中具有相同的具体方法,且
    两个 trait 继承自相同的 trait(TraitC),及所谓的“钻石问题”,解决这类冲突问题,Scala
    采用了特质叠加的策略。
    在这里插入图片描述
    所谓的特质叠加,就是将混入的多个 trait 中的冲突方法叠加起来,案例如下,

trait Ball {def describe(): String = {"ball"}
}
trait Color extends Ball {override def describe(): String = {"blue-" + super.describe()}
}
trait Category extends Ball {override def describe(): String = {"foot-" + super.describe()}
}
class MyBall extends Category with Color {override def describe(): String = {"my ball is a " + super.describe()}
}
object TestTrait {def main(args: Array[String]): Unit = {println(new MyBall().describe())}
}

结果如下:

在这里插入图片描述

6.7.4 特质叠加执行顺序

思考: 上述案例中的 super.describe()调用的是父 trait 中的方法吗?

  • 当一个类混入多个特质的时候,scala 会对所有的特质及其父特质按照一定的顺序进行
    排序,而此案例中的 super.describe()调用的实际上是排好序后的下一个特质中的 describe()
    方法。,排序规则如下:
    在这里插入图片描述

结论:
在这里插入图片描述
在这里插入图片描述

6.7.5 特质自身类型

1)说明

  • 自身类型可实现依赖注入的功能。

2)案例实操

class User(val name: String, val age: Int)
trait Dao {def insert(user: User) = {println("insert into database :" + user.name)}
}
trait APP {_: Dao =>def login(user: User): Unit = {println("login :" + user.name)insert(user)}
}
object MyApp extends APP with Dao {def main(args: Array[String]): Unit = {login(new User("bobo", 11))}
}

6.7.6 特质和抽象类的区别

1.优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。
2.如果你需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,
而特质不行(有无参构造)。
3.特质(Trait)和抽象类(Abstract Class)是Scala语言中两种常见的代码组织方式,它们有一些区别和特点。

  1. 继承关系:特质和抽象类都可以被其他类继承。但是,一个类只能继承一个抽象类,而可以同时继承多个特质(多重继承)。

  2. 单继承 vs. 多重混入:由于Scala只支持单继承,所以通过继承一个抽象类,子类只能继承一个父类的特性。而通过混入特质,可以将多个特质的功能组合到一个类中,实现多重混入。

  3. 构造器:抽象类可以有构造器,而特质不能直接拥有构造器。特质可以通过在类中混入时传递参数的方式来影响类的行为。

  4. 抽象方法和具体方法:抽象类可以包含抽象方法和具体方法。抽象方法只有声明而没有具体实现,由子类实现。而特质可以包含抽象方法和具体方法,特质中的方法默认是抽象的,但也可以提供默认的实现。

  5. 实例化:抽象类不能直接实例化,只能被继承。而特质也不能直接实例化,但可以通过混入到具体类中来影响类的行为。

  6. 使用场景:抽象类通常用于定义一些共性的行为和状态,被子类继承和扩展。特质通常用于定义一些可复用的代码片段,可以被多个类混入,实现代码的复用和模块化。

总而言之,特质和抽象类在Scala中有不同的用途和特点。抽象类用于定义类的继承关系和共性行为,而特质用于实现代码的复用和模块化,可以多重混入到类中。根据具体的需求,可以选择合适的方式来组织代码结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/9663.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新颖的文档、视频交互方式:以《GPT API Unofficial Docs》和《渐构》为例

一、背景 无意中看到一份 《GPT API 非官方文档》:https://gpt.pomb.us/ 被网站的交互方式所吸引,颇为新颖,值得借鉴。 左侧是对应的 API 代码调用示例,右侧是文档的每个部分,滑动到对应部分,左侧相关的代…

【UnityDOTS 十一】SharedComponent介绍

SharedComponent介绍 SharedComponent内存图 共享组件的值数组在单独的SharedComponentDataArrary中。每个Chunk中有一个单独的Handle指向这个值。 所以这个Chunk中放的不只是ArcheType相同的Entity,他们所指向的ShareComponent值也是相同的。 同时修改一个Entity…

PostgreSQL如何根据执行计划进行性能调优?

EXPLAIN命令 PG中EXPLAIN命令语法格式如下: EXPLAIN [(option[,...])] statement EXPLAIN [ANALYZE] [VERBOSE] statement该命令的options如下: ANALYZE [boolean]VERBOSE [boolean]COSTS [boolean]BUFFERS [boolean]FORMAT {TEXT | XML | JSON | YAM…

20.BeautifulSoup库的安装及导入

文章目录 1.BeautifulSoup库简介2.BeautifulSoup库的安装3.BeautifulSoup和beautifulsoup4的区别4.获取网页源代码知识回顾4.1 手动获取网页的源代码4.2 requests库获取网页的源代码 5. 利用bs4库输出网页源代码6.bs4库的导入语法 1.BeautifulSoup库简介 BeautifulSoup库是Pyt…

【机器学习】机器故障的二元分类模型-Kaggle竞赛

竞赛介绍 数据集描述 本次竞赛的数据集(训练和测试)是从根据机器故障预测训练的深度学习模型生成的。特征分布与原始分布接近,但不完全相同。随意使用原始数据集作为本次竞赛的一部分,既可以探索差异,也可以了解在训…

Vue中的el-date-picker时间选择器的使用

1、value-format属性设置需要什么格式的时间 2、type类型选择datetime、date 年月日时分秒 <el-date-pickervalue-format"yyyy-MM-dd HH:mm:ss"v-model"excelRuleForm.startTime"type"datetime":placeholder"选择开始时间"> &…

Web3 处理智能合约部署到本地区块链,并在本地进行测试

上文 Web3 在Truffle项目中编写出自己的第一个solidity智能合约我们演示了 在Truffle环境下写一个智能合约并编译的功能 编译出的文件夹中的这个JSON就非常重要了 我们就可以通过 它这个ABI链接到需要的智能合约程序上去 但这也仅仅是编译完了 我们的智能合约还没有部署到我们…

SpringBoot--超时熔断器

需求背景 如果一个服务中有很多涉及需要服务间熔断的地方&#xff0c;就会出现N多下述代码&#xff1a; 1.N个fegnClient接口 FeignClient(name "hello-world-service", fallback HelloWorldFallback.class) public interface HelloWorldService {GetMapping(&q…

HDLBits刷题笔记9:Circuits.Sequential Logic.Counters + Shift Registers

Counters Four-bit binary counter module top_module (input clk,input reset, // Synchronous active-high resetoutput reg [3:0] q);always (posedge clk) beginif(reset)q < 0;elseq < q 1;end endmoduleDecade counter 建立一个计数器&#xff0c;从0计数…

【深度学习】深度强化学习初学者指南

一、说明 GAN&#xff08;Generative Adversarial Networks&#xff09;是一种深度学习模型&#xff0c;它由两个神经网络组成&#xff1a;一个生成网络和一个判别网络。生成网络学习如何生成类似于给定数据集的新数据&#xff0c;而判别网络则学习如何区分生成网络生成的数据和…

vscode 插件系统的运行机制!

做vscode二次开发有一段时间了&#xff0c;平时都是任务比较重&#xff0c;最近有时间做下总结&#xff0c;详细的讲解下vscode 插件系统的运行机制&#xff0c;vscode做为最受欢迎的编辑器&#xff0c;有着庞大的插件市场。其插件系统确实很复杂&#xff0c;文章很长&#xff…

Maven基础概念

仓库 作用&#xff1a;用于存储资源&#xff0c;包含各种jar包 仓库分类 本地仓库远程仓库 2.1中央仓库 2.2私服&#xff08;用于解决下载速度慢&#xff0c;版权问题等&#xff09; 1.maven坐标 <groupId></groupId>当前MAVEN项目隶属组织名称 <artifactId…