- Scala 教程
- Scala - 首页
- Scala - 概述
- Scala - 特性
- Scala - 环境设置
- Scala - 构建工具 (SBT)
- Scala - 基本语法
- 数据类型和变量
- Scala - 数据类型
- Scala - 变量
- Scala - 字符串
- Scala - 数组
- Scala 运算符
- Scala - 运算符
- Scala - 算术运算符
- Scala - 关系运算符
- Scala - 逻辑运算符
- Scala - 位运算符
- Scala - 赋值运算符
- Scala 条件语句
- Scala - IF ELSE
- Scala 循环语句
- Scala - 循环语句
- Scala - while 循环
- Scala - do-while 循环
- Scala - for 循环
- Scala - break 语句
- Scala 类和对象
- Scala - 类和对象
- Scala - 访问修饰符
- Scala 方法和函数
- Scala - 函数
- Scala - 按名称调用函数
- Scala - 带有名称参数的函数
- Scala - 带有可变参数的函数
- Scala - 递归函数
- Scala - 默认参数值
- Scala - 高阶函数
- Scala - 嵌套函数
- Scala - 匿名函数
- 部分应用函数
- Scala - Currying 函数
- Scala 集合
- Scala - 集合
- Scala - 列表
- Scala - 集合
- Scala - 映射
- Scala - 元组
- Scala - 迭代器
- Scala - 选项
- Scala 模式匹配
- Scala - 模式匹配
- Scala - 异常处理
- Scala - 提取器
- Scala - 正则表达式
- Scala 文件 I/O
- Scala - 文件 I/O
- Scala 高级概念
- Scala - 闭包
- Scala - 特性
- Scala 有用资源
- Scala - 快速指南
- Scala - 在线编译器
- Scala - 有用资源
- Scala - 讨论
Scala - 特性
特性封装了方法和字段的定义,然后可以通过将它们混合到类中来重用。与类继承不同,在类继承中每个类都必须从一个超类继承,一个类可以混合任意数量的特性。
特性用于通过指定支持方法的签名来定义对象类型。Scala 还允许特性被部分实现,但特性不能有构造函数参数。
特性定义看起来就像类定义,只是它使用关键字trait。以下是特性的基本示例语法。
语法
trait Equal { def isEqual(x: Any): Boolean def isNotEqual(x: Any): Boolean = !isEqual(x) }
此特性包含两个方法isEqual 和 isNotEqual。在这里,我们没有为 isEqual 提供任何实现,而另一个方法有其实现。扩展特性的子类可以为未实现的方法提供实现。因此,特性非常类似于我们在 Java 中拥有的抽象类。
让我们假设一个特性Equal包含两个方法isEqual() 和 isNotEqual() 的示例。特性Equal包含一个已实现的方法,即isEqual(),因此当用户定义的类Point扩展特性Equal时,应在Point类中提供isEqual()方法的实现。
这里需要了解 Scala 的两个重要方法,它们在下面的示例中使用。
obj.isInstanceOf [Point] 用于检查 obj 和 Point 的类型是否相同。
obj.asInstanceOf [Point] 表示通过获取对象 obj 类型并将其作为 Point 类型返回来进行精确转换。
尝试以下示例程序来实现特性。
示例
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 扩展值类来实现。自定义数据类型的类型安全,没有运行时开销。
让我们以值类 Weight、Height、Email、Age 等为例。对于所有这些示例,不需要在应用程序中分配内存。
值类不允许扩展特性。为了允许值类扩展特性,引入了通用特性,它扩展了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
何时使用特性?
没有硬性规定,但以下是一些需要考虑的指导原则:
如果行为不会被重用,则将其设为具体类。毕竟它不是可重用的行为。
如果它可能在多个不相关的类中重用,则将其设为特性。只有特性才能混合到类层次结构的不同部分。
如果要从 Java 代码中继承它,请使用抽象类。
如果计划以编译的形式分发它,并且您期望外部组编写从中继承类的类,那么您可能会倾向于使用抽象类。
如果效率非常重要,请倾向于使用类。