自闭症康复网,内容丰富有趣,生活中的好帮手!
自闭症康复网 > Scala特证/特质【6.7 特质(Trait)】

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

时间:2022-02-20 16:43:26

相关推荐

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中被广泛应用于各种编程场景,例如回调机制、事件处理、依赖注入等。

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

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

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

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

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

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

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

抽象类的作用

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

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

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

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

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

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

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

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语言中两种常见的代码组织方式,它们有一些区别和特点。

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

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

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

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

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

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

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

如果觉得《Scala特证/特质【6.7 特质(Trait)】》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
Scala中的trait特质

Scala中的trait特质

2023-11-16

Scala特质(特征)Trait

Scala特质(特征)Trait

2023-06-16

scala的特质(trait)

scala的特质(trait)

2019-11-17

Scala 034 特质trait

Scala 034 特质trait

2023-09-02