一、内部类的定义
在 Scala 中,内部类是定义在另一个类(外部类)内部的类。它的语法形式如下:
class 外部类 { class 内部类 { // 内部类的成员定义 } }
内部类与外部类有着紧密的关联,它可以直接访问外部类的所有成员(包括私有成员),这是内部类实现高内聚封装的关键特性。
二、内部类的基本使用
我们通过一个简单的示例来演示内部类的基本使用:
package A2
object class15 {
// 外部类:学校
class School(val name: String) {
// 内部类:学生
class Student(val id: Int, var name: String) {
def study(): Unit = {
println(s"${this.name}(学号:$id)在${School.this.name}学校学习")
}
}
// 创建学生对象的方法
def createStudent(id: Int, name: String): Student = {
new Student(id, name)
}
}
// 测试代码
object InnerClassDemo {
def main(args: Array[String]): Unit = {
val school = new School("北京大学")
val student1 = school.createStudent(1, "张三")
student1.study()
val student2 = school.createStudent(2, "李四")
student2.study()
}
}
}
在上述代码中,Student类是School类的内部类。需要注意的是,Scala 的内部类是 “路径依赖” 的,即不同外部类实例的内部类是不同的类型。例如,若有val school2 = new School("清华大学"),则school.createStudent(...)的类型与school2.createStudent(...)的类型并不兼容。
三、内部类的使用案例:小汽车与发动机的封装
我们按照案例要求,实现一个包含内部类的小汽车系统:
package A2
object class15 {
// 外部类:小汽车
class Car {
// 私有变量:速度
private var speed: Double = 0.0
// 内部类:发动机
class Engine {
// 加速方法:修改外部类的私有变量speed
def accelerate(inc: Double): Unit = {
speed += inc
println(s"加速后,车速为:$speed km/h")
}
// 减速方法
def decelerate(dec: Double): Unit = {
speed = if (speed - dec < 0) 0 else speed - dec
println(s"减速后,车速为:$speed km/h")
}
}
// 获取发动机对象的方法
def getEngine: Engine = {
new Engine
}
}
// 测试代码
object CarDemo {
def main(args: Array[String]): Unit = {
val car = new Car
val engine = car.getEngine
engine.accelerate(50)
engine.accelerate(30)
engine.decelerate(20)
}
}
}
在这个案例中,Engine作为Car的内部类,能够直接访问Car的私有变量speed,从而实现对车速的修改。这种设计将 “发动机” 与 “小汽车” 的逻辑紧密封装在一起,符合面向对象的高内聚原则。
四、内部对象
在 Scala 中,除了内部类,还可以定义内部对象(也称为嵌套对象)。内部对象是定义在类或对象内部的单例对象,它常用于实现类的伴生对象、工具类封装等场景。
示例如下:
package A2
object class15 {
class MathUtils {
// 内部对象:包含数学工具方法
object Calculator {
def add(a: Int, b: Int): Int = a + b
def multiply(a: Int, b: Int): Int = a * b
}
}
// 测试内部对象
object InnerObjectDemo {
def main(args: Array[String]): Unit = {
val math = new MathUtils
println(s"2 + 3 = ${math.Calculator.add(2, 3)}")
println(s"2 × 3 = ${math.Calculator.multiply(2, 3)}")
}
}
}
内部对象的一个典型应用是伴生对象的嵌套,例如在一个内部类中定义其伴生对象,用于创建该内部类的实例:
package A2
object class15 {
class Outer {
class Inner private(val name: String)
// 内部伴生对象
object Inner {
def apply(name: String): Inner = new Inner(name)
}
}
object OuterDemo {
def main(args: Array[String]): Unit = {
val outer = new Outer
val inner = outer.Inner("内部类实例")
println(inner.name)
}
}
}
匿名类是指没有显式命名的类,它通常用于快速实现一个特质(trait)或抽象类的实例,而无需定义一个新的具名类。
在 Scala 中,匿名类的语法形式为:new 特质/抽象类 { 实现代码 }
5.1 匿名类实现特质
package A2
object class15 {
// 定义一个特质
trait Greeting {
def sayHello(name: String): Unit
}
// 使用匿名类实现特质
object AnonymousClassDemo {
def main(args: Array[String]): Unit = {
val chineseGreeting = new Greeting {
override def sayHello(name: String): Unit = {
println(s"你好,$name!")
}
}
val englishGreeting = new Greeting {
override def sayHello(name: String): Unit = {
println(s"Hello, $name!")
}
}
chineseGreeting.sayHello("张三")
englishGreeting.sayHello("John")
}
}
}
5.2 匿名类实现抽象类
package A2
object class15 {
// 抽象类
abstract class Animal {
def sound(): Unit
}
// 匿名类实现抽象类
object AnimalDemo {
def main(args: Array[String]): Unit = {
val dog = new Animal {
override def sound(): Unit = {
println("汪汪汪!")
}
}
val cat = new Animal {
override def sound(): Unit = {
println("喵喵喵!")
}
}
dog.sound()
cat.sound()
}
}
}
匿名类的优势在于快速原型开发和代码简洁性,尤其在只需要一个类的单次实例时,避免了定义具名类的繁琐。
总结
本文围绕 Scala 的内部类、内部对象和匿名类展开,从定义、基本使用到实战案例,全面解析了这些特性的用法与价值:
- 内部类通过嵌套定义实现类之间的强逻辑关联,支持访问外部类私有成员,是封装复杂逻辑的有力工具。
- 内部对象常用于工具方法封装、伴生对象嵌套等场景,提升代码的内聚性。
- 匿名类则让我们可以快速实现特质或抽象类的实例,简化代码结构,尤其适用于临时逻辑的快速实现。