Scala 特征(Traits)
特征(Traits)封装了方法和字段定义,可以通过将其混入类中来重用。与类继承不同,在类继承中,每个类只能继承一个超类,而类可以混入任意数量的特征。
特征用于通过指定支持的方法的签名来定义对象类型。Scala还允许对特征进行部分实现,但是特征不能有构造函数参数。
特征定义看起来和类定义一样,只是使用关键字 trait 。以下是特征的基本示例语法。
语法
这个特质由两个方法组成 isEqual 和 isNotEqual 。在这里,我们没有给isEqual方法提供任何实现,而另一个方法则有它的实现。继承特质的子类可以为未实现的方法提供实现。因此,特质与Java中的抽象类非常相似。
让我们假设一个特质 Equal 的示例,其中包含两个方法 isEqual() 和 isNotEqual() 。特质 Equal 包含一个已实现的方法 isEqual() ,因此当用户定义的类 Point 扩展特质 Equal 时,需要提供 Point 类中 isEqual() 方法的实现。
在这里,有两个Scala中使用的重要方法需要了解,它们在以下示例中使用。
- obj.isInstanceOf [Point] 检查obj和Point的类型是否相同。
-
obj.asInstanceOf [Point] 表示通过将对象obj的类型转换为Point类型来进行准确的类型转换,并返回相同的obj。
尝试以下示例程序来实现特质。
示例
将上述程序保存在 Demo.scala 文件中。使用以下命令编译和执行该程序。
命令
输出
值类和通用特质
值类是Scala中避免分配运行时对象的新机制。它包含一个具有 val 参数的主构造函数。它只包含方法(def),不允许使用var、val、嵌套类、特质或对象。值类不能被另一个类继承。通过将您的值类扩展为AnyVal,可以实现自定义数据类型的类型安全性,而不会增加运行时开销。
让我们以值类Weight、Height、Email、Age等为例。对于所有这些示例,在应用程序中不需要分配内存。
值类不允许扩展特质。为了允许值类扩展特质,引入了扩展任何类型的 通用特质 。
示例
将上述程序保存在 Demo.scala 中。以下命令用于编译和执行程序。
命令
输出
它将给出Wrapper类的哈希码。
什么时候使用Traits?
并没有明确的规定,但以下是一些考虑因素:
-
如果行为不会被重用,那么将其作为一个具体类。毕竟它不是可重用的行为。
-
如果可能在多个无关的类中重用它,那么将其作为一个trait。只有trait可以混合到类层次结构的不同部分中。
-
如果你想在Java代码中从中继承,使用一个抽象类。
-
如果你计划以编译形式分发它,并且你期望外部组织编写从中继承的类,那么你可能倾向于使用一个抽象类。
-
如果效率非常重要,倾向于使用一个类。