- Scala Tutorial
- Scala - Home
- Scala - Overview
- Scala - Environment Setup
- Scala - Basic Syntax
- Scala - Data Types
- Scala - Variables
- Scala - Classes & Objects
- Scala - Access Modifiers
- Scala - Operators
- Scala - IF ELSE
- Scala - Loop Statements
- Scala - Functions
- Scala - Closures
- Scala - Strings
- Scala - Arrays
- Scala - Collections
- Scala - Traits
- Scala - Pattern Matching
- Scala - Regular Expressions
- Scala - Exception Handling
- Scala - Extractors
- Scala - Files I/O
- Scala Useful Resources
- Scala - Quick Guide
- Scala - Useful Resources
- Scala - Discussion
Scala - 特性
特征封装了方法和字段定义,然后可以通过将它们混合到类中来重用它们。与类继承(其中每个类必须仅继承一个超类)不同,类可以混合任意数量的特征。
特征用于通过指定受支持方法的签名来定义对象类型。Scala 还允许部分实现特征,但特征可能没有构造函数参数。
特征定义看起来就像类定义,只是它使用关键字Trait。以下是 Trait 的基本示例语法。
句法
trait Equal { def isEqual(x: Any): Boolean def isNotEqual(x: Any): Boolean = !isEqual(x) }
此特征由两个方法isEqual和isNotEqual组成。在这里,我们没有给出 isEqual 的任何实现,而另一个方法有其实现。扩展特征的子类可以为未实现的方法提供实现。因此,trait 与Java 中的抽象类非常相似。
让我们假设特征Equal的示例包含两个方法isEqual()和isNotEqual()。Trait Equal包含一个实现方法 isEqual (),因此当用户定义的类Point扩展 Trait Equal时,应提供Point类中isEqual()方法的实现。
这里需要了解Scala的两个重要方法,下面的例子中会用到这两个方法。
obj.isInstanceOf [Point]检查 obj 和 Point 的类型是否相同。
obj.asInstanceOf [Point]表示通过获取对象 obj 类型进行精确转换,并返回与 Point 类型相同的 obj。
尝试以下示例程序来实现特征。
例子
trait Equal { def isEqual(x: Any): Boolean def isNotEqual(x: Any): Boolean = !isEqual(x) } class Point(xc: Int, yc: Int) extends Equal { var x: Int = xc var y: Int = yc def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == y } object Demo { def main(args: Array[String]) { val p1 = new Point(2, 3) val p2 = new Point(2, 4) val p3 = new Point(3, 3) println(p1.isNotEqual(p2)) println(p1.isNotEqual(p3)) println(p1.isNotEqual(2)) } }
将上述程序保存在Demo.scala中。以下命令用于编译和执行该程序。
命令
\>scalac Demo.scala \>scala Demo
输出
true false true
价值类别和普遍特征
值类是 Scala 中避免分配运行时对象的新机制。它包含一个带有一个val参数的主构造函数。它仅包含方法 (def),不允许使用 var、val、嵌套类、特征或对象。值类不能由另一个类扩展。这可以通过使用 AnyVal 扩展您的值类来实现。自定义数据类型的类型安全性,无需运行时开销。
让我们以体重、身高、电子邮件、年龄等值类为例。对于所有这些示例,不需要在应用程序中分配内存。
不允许扩展特征的值类。为了允许值类扩展特征,引入了扩展Any的通用特征。
例子
trait Printable extends Any { def print(): Unit = println(this) } class Wrapper(val underlying: Int) extends AnyVal with Printable object Demo { def main(args: Array[String]) { val w = new Wrapper(3) w.print() // actually requires instantiating a Wrapper instance } }
将上述程序保存在Demo.scala中。以下命令用于编译和执行该程序。
命令
\>scalac Demo.scala \>scala Demo
输出
它会给你 Wrapper 类的哈希码。
Wrapper@13
何时使用特征?
没有严格的规则,但这里有一些需要考虑的准则 -
如果该Behave不会被重用,则将其设为具体类。毕竟这不是可重用的Behave。
如果它可以在多个不相关的类中重用,请将其设为特征。只有特征可以混合到类层次结构的不同部分中。
如果要在 Java 代码中继承它,请使用抽象类。
如果您计划以编译形式分发它,并且希望外部组编写继承它的类,那么您可能倾向于使用抽象类。
如果效率非常重要,那么倾向于使用类。