1. 内部类的定义;
2. 内部类的基本使用;
3. 内部类的综合案例;
4. 内部对象;
5. 匿名类。
(一)内部类的定义
定义在类或者对象内部的类称为内部类。
在类的内部有:属性,方法,类。
1. 基本语法
内部类的基本定义格式
class OuterClass { // 外部类
// 外部类的成员
class InnerClass { // 内部类
// 内部类的成员
}
}
具体示例
object InnerClassDefinition {
// 外部类
class Car(val brand: String, var speed: Int = 0) {
// 外部类属性
private val maxSpeed: Int = 200
// 外部类方法
def accelerate(amount: Int): Unit = {
speed = Math.min(speed + amount, maxSpeed)
println(s"$brand 加速到 $speed km/h")
}
// 内部类定义
class Engine(val engineType: String, val horsepower: Int) {
// 内部类属性
private var isRunning: Boolean = false
// 内部类方法
def start(): Unit = {
if (!isRunning) {
isRunning = true
println(s"$brand 的 $engineType 引擎启动,马力: $horsepower")
// 内部类可以访问外部类的成员
accelerate(20)
}
}
def stop(): Unit = {
if (isRunning) {
isRunning = false
println(s"$brand 的引擎停止")
speed = 0
}
}
def getStatus(): String = {
s"引擎类型: $engineType, 运行状态: $isRunning, 当前车速: $speed"
}
// 内部类可以访问外部类的私有成员
def canReachMaxSpeed(): Boolean = {
horsepower >= 150 && maxSpeed >= 180
}
}
}
}
2. 内部类的实例化
创建内部类对象
object InnerClassInstantiation {
class University(val name: String) {
class Department(val deptName: String) {
def info(): String = s"$name - $deptName"
}
}
def main(args: Array[String]): Unit = {
// 创建外部类实例
val tsinghua = new University("清华大学")
val beida = new University("北京大学")
// 创建内部类实例(必须通过外部类实例)
val tsinghuaCS = new tsinghua.Department("计算机系")
val tsinghuaMath = new tsinghua.Department("数学系")
val beidaCS = new beida.Department("计算机系")
println(tsinghuaCS.info()) // 清华大学 - 计算机系
println(tsinghuaMath.info()) // 清华大学 - 数学系
println(beidaCS.info()) // 北京大学 - 计算机系
// 类型路径依赖
println(s"类型比较: ${tsinghuaCS.getClass == beidaCS.getClass}") // false
}
}
3. 内部类访问外部类成员
完整的访问权限示例
object InnerClassAccess {
class Bank(val bankName: String) {
private var totalBalance: Double = 0.0
private val interestRate: Double = 0.03
class Account(val accountHolder: String, var balance: Double) {
// 内部类可以访问外部类的私有字段
def deposit(amount: Double): Unit = {
balance += amount
totalBalance += amount // 修改外部类的私有字段
println(s"$accountHolder 存款 $amount, 余额: $balance")
}
def withdraw(amount: Double): Boolean = {
if (balance >= amount) {
balance -= amount
totalBalance -= amount
println(s"$accountHolder 取款 $amount, 余额: $balance")
true
} else {
println(s"$accountHolder 取款失败,余额不足")
false
}
}
def applyInterest(): Unit = {
val interest = balance * interestRate // 访问外部类私有常量
balance += interest
totalBalance += interest
println(s"$accountHolder 获得利息 $interest, 新余额: $balance")
}
def getBankInfo(): String = {
s"银行: $bankName, 总余额: $totalBalance" // 访问外部类字段
}
}
def getTotalBalance(): Double = totalBalance
def getAccountCount(): Int = {
// 这里无法直接获取内部类实例数量,需要其他机制
0
}
}
def main(args: Array[String]): Unit = {
val bank = new Bank("中国银行")
val account1 = new bank.Account("张三", 1000)
val account2 = new bank.Account("李四", 2000)
account1.deposit(500)
account2.withdraw(300)
account1.applyInterest()
println(account1.getBankInfo())
println(s"银行总余额: ${bank.getTotalBalance()}")
}
}
4. 多层内部类
嵌套的内部类结构
object MultiLevelInnerClass {
class Company(val companyName: String) {
private var totalEmployees = 0
class Department(val deptName: String) {
private var deptEmployees = 0
class Team(val teamName: String) {
private var teamMembers = 0
def hire(employee: String): Unit = {
teamMembers += 1
deptEmployees += 1
totalEmployees += 1
println(s"$companyName - $deptName - $teamName 招聘: $employee")
println(s"团队人数: $teamMembers, 部门人数: $deptEmployees, 公司总人数: $totalEmployees")
}
class Employee(val name: String, val position: String) {
def work(): Unit = {
println(s"$name ($position) 在 $companyName - $deptName - $teamName 工作")
}
def getOrgPath(): String = {
s"$companyName -> $deptName -> $teamName -> $name"
}
}
}
def createTeam(teamName: String): Team = {
new Team(teamName)
}
}
def createDepartment(deptName: String): Department = {
new Department(deptName)
}
}
def main(args: Array[String]): Unit = {
val company = new Company("阿里巴巴")
val techDept = company.createDepartment("技术部")
val marketDept = company.createDepartment("市场部")
val backendTeam = techDept.createTeam("后端团队")
val frontendTeam = techDept.createTeam("前端团队")
val salesTeam = marketDept.createTeam("销售团队")
backendTeam.hire("张三")
frontendTeam.hire("李四")
salesTeam.hire("王五")
// 创建最内层的内部类
val employee1 = new backendTeam.Employee("赵六", "高级工程师")
employee1.work()
println(employee1.getOrgPath())
}
}
5. 内部类的类型路径
路径依赖类型
object PathDependentTypes {
class Container(val id: String) {
class Item(val name: String) {
def describe(): String = s"容器 $id 中的物品 $name"
}
}
def processItem(item: Container#Item): Unit = {
// Container#Item 是类型投影,不依赖特定实例
println(s"处理: ${item.name}")
}
def main(args: Array[String]): Unit = {
val container1 = new Container("A")
val container2 = new Container("B")
val item1 = new container1.Item("书籍")
val item2 = new container2.Item("电脑")
// 这些是不同类型
// val item3: container1.Item = new container2.Item("手机") // 编译错误
// 使用类型投影可以接受任何容器的Item
processItem(item1)
processItem(item2)
println(item1.describe()) // 容器 A 中的物品 书籍
println(item2.describe()) // 容器 B 中的物品 电脑
}
}
关键特点总结:
- 定义位置:在外部类的内部定义
- 实例绑定:每个内部类实例与特定的外部类实例关联
- 访问权限:可以访问外部类的所有成员(包括私有成员)
- 类型路径:
outerInstance.InnerClass是路径依赖类型 - 创建方式:必须通过外部类实例创建
new outer.Inner() - 内存模型:内部类隐式持有对外部类实例的引用
(二)内部类的基本使用
定义格式: class 类 { class 内部类 }
使用格式: new 类的实例.内部类()
/*
* 内部类
***/
object Main {
// 外部类
class Car() {
var wheel: Int = 4
def run(): Unit = {
println("run...")
}
// 内部类
class Engine() {
val power: Int = 120
def start(): Unit = {
println("引擎启动")
}
}
}
def main(args: Array[String]): Unit = {
val car = new Car()
// Scala 中创建内部类的方式
val engine = new car.Engine()
println(engine.power)
engine.start()
car.run()
}
}
关键点总结:
- 创建语法:
new outerInstance.InnerClass() - 实例绑定:内部类实例与特定的外部类实例绑定
- 访问权限:内部类可以访问外部类的所有成员(包括私有成员)
- 类型路径:
car1.Engine和car2.Engine是不同的类型 - 内存模型:内部类持有对外部类实例的引用
内部类的好处
(1)逻辑组织:引擎与 汽车紧密相关,它们都属于汽车的上下文。将它们作为内部类可以使代码更为整洁和逻辑清晰。
(2)简化访问:内部类能够方便地访问外部类的私有成员,这样引擎类可以操作汽车的速度而不需要通过外部接口。
(3)减少命名冲突:由于内部类的作用范围限制在外部类内,避免了名称冲突(在大型项目中,可能会有多个引擎类)。
(三)内部类的使用案例
1. 游戏角色系统
object GameCharacterExample {
class GameCharacter(val name: String, var health: Int = 100) {
private var position: (Int, Int) = (0, 0)
private var experience: Int = 0
// 装备内部类
class Equipment(val slot: String) {
private var item: Option[String] = None
def equip(itemName: String): Unit = {
item = Some(itemName)
println(s"$name 装备了 $slot: $itemName")
}
def unequip(): Unit = {
item.foreach { oldItem =>
println(s"$name 卸下了 $slot: $oldItem")
}
item = None
}
def getItem: Option[String] = item
def applyBonus(): Int = item match {
case Some("王者之剑") => 20
case Some("守护之盾") => 15
case Some("疾风之靴") => 10
case _ => 0
}
}
// 技能内部类
class Skill(val skillName: String, val cost: Int) {
def use(target: GameCharacter): Unit = {
if (health > cost) {
health -= cost
experience += 5
val damage = 10 + (experience / 10)
target.health -= damage
println(s"$name 对 ${target.name} 使用 $skillName, 造成 $damage 伤害")
} else {
println(s"生命值不足,无法使用 $skillName")
}
}
def upgrade(): Unit = {
println(s"$skillName 技能升级!")
}
}
// 背包内部类
class Inventory {
private var items: List[String] = List()
private val capacity = 10
def addItem(item: String): Boolean = {
if (items.length < capacity) {
items = item :: items
println(s"$name 获得了 $item")
true
} else {
println("背包已满")
false
}
}
def useItem(item: String): Boolean = {
if (items.contains(item)) {
items = items.filter(_ != item)
item match {
case "治疗药水" => health = Math.min(health + 30, 100)
case "魔力药水" => experience += 10
}
println(s"$name 使用了 $item")
true
} else {
println(s"没有 $item")
false
}
}
def showItems(): Unit = {
println(s"$name 的背包: ${items.mkString(", ")}")
}
}
def moveTo(x: Int, y: Int): Unit = {
position = (x, y)
println(s"$name 移动到位置 ($x, $y)")
}
def showStatus(): Unit = {
println(s"角色: $name, 生命: $health, 经验: $experience, 位置: $position")
}
}
def main(args: Array[String]): Unit = {
val warrior = new GameCharacter("战士")
val mage = new GameCharacter("法师", 80)
// 创建装备
val weapon = new warrior.Equipment("武器")
val armor = new warrior.Equipment("护甲")
val boots = new warrior.Equipment("靴子")
// 创建技能
val slash = new warrior.Skill("斩击", 15)
val fireball = new mage.Skill("火球术", 20)
// 创建背包
val inventory = new warrior.Inventory()
warrior.showStatus()
// 装备物品
weapon.equip("王者之剑")
armor.equip("守护之盾")
boots.equip("疾风之靴")
// 使用技能
slash.use(mage)
fireball.use(warrior)
// 背包操作
inventory.addItem("治疗药水")
inventory.addItem("魔力药水")
inventory.showItems()
inventory.useItem("治疗药水")
warrior.showStatus()
mage.showStatus()
}
}
2. 电商订单系统
object ECommerceExample {
class Order(val orderId: String, val customer: String) {
private var orderStatus: String = "待支付"
private var totalAmount: Double = 0.0
private var paymentMethod: Option[String] = None
// 订单项内部类
class OrderItem(val productId: String, val productName: String, var quantity: Int, val unitPrice: Double) {
def calculateSubtotal(): Double = quantity * unitPrice
def updateQuantity(newQuantity: Int): Unit = {
totalAmount -= calculateSubtotal() // 减去旧的
quantity = newQuantity
totalAmount += calculateSubtotal() // 加上新的
println(s"更新数量: $productName × $newQuantity")
}
def getItemInfo(): String = {
s"$productName (ID: $productId) - $quantity × ¥$unitPrice = ¥${calculateSubtotal()}"
}
}
// 支付内部类
class Payment {
def processPayment(method: String, amount: Double): Boolean = {
if (orderStatus == "待支付" && amount >= totalAmount) {
paymentMethod = Some(method)
orderStatus = "已支付"
println(s"订单 $orderId 支付成功,方式: $method,金额: ¥$amount")
true
} else {
println("支付失败")
false
}
}
def refund(reason: String): Boolean = {
if (orderStatus == "已支付") {
orderStatus = "已退款"
println(s"订单 $orderId 退款成功,原因: $reason")
true
} else {
println("无法退款")
false
}
}
}
// 物流内部类
class Shipping {
private var trackingNumber: Option[String] = None
private var shippingAddress: String = ""
def setAddress(address: String): Unit = {
shippingAddress = address
println(s"设置收货地址: $address")
}
def ship(tracking: String): Unit = {
if (orderStatus == "已支付") {
trackingNumber = Some(tracking)
orderStatus = "已发货"
println(s"订单 $orderId 已发货,物流单号: $tracking")
} else {
println("订单未支付,无法发货")
}
}
def track(): Unit = {
trackingNumber match {
case Some(tracking) => println(s"物流跟踪: $tracking -> $shippingAddress")
case None => println("尚未发货")
}
}
}
def addItem(item: OrderItem): Unit = {
totalAmount += item.calculateSubtotal()
}
def getOrderSummary(): String = {
s"订单 $orderId - 客户: $customer, 状态: $orderStatus, 总金额: ¥$totalAmount, 支付方式: ${paymentMethod.getOrElse("未支付")}"
}
}
def main(args: Array[String]): Unit = {
val order = new Order("ORD001", "张三")
// 创建订单项
val item1 = new order.OrderItem("P001", "iPhone 15", 1, 5999.0)
val item2 = new order.OrderItem("P002", "AirPods", 2, 1299.0)
// 添加到订单
order.addItem(item1)
order.addItem(item2)
println(order.getOrderSummary())
println(item1.getItemInfo())
println(item2.getItemInfo())
// 更新数量
item2.updateQuantity(1)
println(order.getOrderSummary())
// 支付
val payment = new order.Payment()
payment.processPayment("支付宝", 7297.0)
// 物流
val shipping = new order.Shipping()
shipping.setAddress("北京市海淀区")
shipping.ship("SF123456789")
shipping.track()
println(order.getOrderSummary())
}
}
3. 学校管理系统
object SchoolManagementExample {
class School(val schoolName: String) {
private var studentCount = 0
// 班级内部类
class Classroom(val grade: Int, val className: String) {
private var students: List[String] = List()
private val teacher: String = s"${grade}年级班主任"
// 学生内部类(嵌套内部类)
class Student(val studentName: String, val studentId: String) {
private var scores: Map[String, Int] = Map()
def enroll(): Unit = {
students = studentName :: students
studentCount += 1
println(s"学生 $studentName 加入 $grade 年级 $className")
}
def addScore(subject: String, score: Int): Unit = {
scores += (subject -> score)
println(s"$studentName 的 $subject 成绩: $score")
}
def getAverageScore(): Double = {
if (scores.isEmpty) 0.0
else scores.values.sum.toDouble / scores.size
}
def getStudentInfo(): String = {
s"学生: $studentName (ID: $studentId), 班级: $grade-$className, 平均分: ${getAverageScore()}"
}
def getClassInfo(): String = {
s"班级: $grade-$className, 班主任: $teacher, 同学: ${students.mkString(", ")}"
}
}
def getStudentList(): List[String] = students
def getClassSummary(): String = {
s"$grade 年级 $className - 学生人数: ${students.length}, 班主任: $teacher"
}
}
// 课程内部类
class Course(val courseName: String, val credit: Int) {
private var enrolledStudents: Set[String] = Set()
def enrollStudent(studentName: String): Unit = {
enrolledStudents += studentName
println(s"$studentName 选修了 $courseName")
}
def getEnrolledStudents(): Set[String] = enrolledStudents
def getCourseInfo(): String = {
s"课程: $courseName, 学分: $credit, 选课人数: ${enrolledStudents.size}"
}
}
def getTotalStudents(): Int = studentCount
}
def main(args: Array[String]): Unit = {
val school = new School("第一中学")
// 创建班级
val class1 = new school.Classroom(1, "一班")
val class2 = new school.Classroom(1, "二班")
// 创建学生
val student1 = new class1.Student("张三", "S001")
val student2 = new class1.Student("李四", "S002")
val student3 = new class2.Student("王五", "S003")
// 学生入学
student1.enroll()
student2.enroll()
student3.enroll()
// 添加成绩
student1.addScore("数学", 95)
student1.addScore("语文", 88)
student2.addScore("数学", 92)
student2.addScore("语文", 85)
// 创建课程
val mathCourse = new school.Course("高等数学", 4)
val physicsCourse = new school.Course("大学物理", 3)
// 选课
mathCourse.enrollStudent("张三")
mathCourse.enrollStudent("李四")
physicsCourse.enrollStudent("张三")
// 输出信息
println(student1.getStudentInfo())
println(student2.getStudentInfo())
println(student1.getClassInfo())
println(class1.getClassSummary())
println(class2.getClassSummary())
println(mathCourse.getCourseInfo())
println(physicsCourse.getCourseInfo())
println(s"学校总人数: ${school.getTotalStudents()}")
}
}
4. 车辆管理系统
object VehicleManagementExample {
class VehicleFleet(val company: String) {
private var totalMileage = 0.0
private var maintenanceCost = 0.0
// 车辆内部类
class Vehicle(val licensePlate: String, val model: String) {
private var currentMileage = 0.0
private var fuelLevel = 100.0
private var needsMaintenance = false
// 行程内部类
class Trip(val driver: String, val destination: String) {
private var distance = 0.0
private var completed = false
def startTrip(initialDistance: Double): Unit = {
distance = initialDistance
println(s"$driver 驾驶 $licensePlate 前往 $destination,开始行程")
}
def updateDistance(additionalDistance: Double): Unit = {
distance += additionalDistance
currentMileage += additionalDistance
totalMileage += additionalDistance
fuelLevel -= additionalDistance * 0.1 // 每公里耗油0.1%
if (fuelLevel < 10) {
println("警告:燃油不足!")
}
if (currentMileage > 10000 && !needsMaintenance) {
needsMaintenance = true
println("车辆需要保养!")
}
}
def completeTrip(): Unit = {
completed = true
println(s"行程完成: $destination, 总距离: $distance 公里")
}
def getTripSummary(): String = {
s"司机: $driver, 目的地: $destination, 距离: $distance 公里, 完成: $completed"
}
}
// 维护内部类
class Maintenance {
def performMaintenance(cost: Double): Unit = {
maintenanceCost += cost
currentMileage = 0 // 重置保养里程
needsMaintenance = false
fuelLevel = 100.0
println(s"车辆 $licensePlate 保养完成,花费: ¥$cost")
}
def refuel(amount: Double): Unit = {
fuelLevel = Math.min(fuelLevel + amount, 100.0)
println(s"车辆 $licensePlate 加油 $amount%,当前油量: $fuelLevel%")
}
}
def getVehicleStatus(): String = {
s"车辆: $licensePlate ($model), 里程: $currentMileage km, 油量: $fuelLevel%, 需要保养: $needsMaintenance"
}
}
def getFleetSummary(): String = {
s"车队: $company, 总里程: $totalMileage km, 总维护成本: ¥$maintenanceCost"
}
}
def main(args: Array[String]): Unit = {
val fleet = new VehicleFleet("顺丰快递")
val truck1 = new fleet.Vehicle("京A12345", "重型卡车")
val van1 = new fleet.Vehicle("京B67890", "厢式货车")
// 创建行程
val trip1 = new truck1.Trip("张三", "上海")
val trip2 = new van1.Trip("李四", "天津")
// 开始行程
trip1.startTrip(0)
trip1.updateDistance(1200)
trip1.completeTrip()
trip2.startTrip(0)
trip2.updateDistance(800)
trip2.completeTrip()
// 车辆维护
val maintenance1 = new truck1.Maintenance()
maintenance1.refuel(50)
maintenance1.performMaintenance(500.0)
// 输出状态
println(truck1.getVehicleStatus())
println(van1.getVehicleStatus())
println(trip1.getTripSummary())
println(trip2.getTripSummary())
println(fleet.getFleetSummary())
}
}
这些案例展示了内部类在实际项目中的应用,体现了内部类与外部类实例的紧密关联性和数据封装的优势。
(四)内部对象
内部对象,就是定义在class内部的object。
定义格式: class 类名 { object 对象名{ 属性;方法() }}
使用格式:类名.对象名.属性名; 类名.对象名.方法名()
/*
* 内部类
* 1. 格式:在一个类的里面,再写一个类
* 2. 作用:组织逻辑更加严谨,避免命名的冲突
*/
object base66 {
// 外部类
class Car() {
var wheel: Int = 4
// 私有成员
private var speed: Int = 0
def run(): Unit = {
println(s"速度为: ${speed}, run...")
}
// 内部类
class Engine() {
def acc(increment: Int): Unit = {
speed += increment // 内部类可以直接访问外部类的私有成员!
}
def getSpeed(): Int = {
speed // 访问私有成员
}
}
class AutoPark() {
def park(): Unit = {
speed = 0 // 另一个内部类也可以访问同一个外部类的私有成员
println("自动泊车完成,速度归零")
}
}
}
def main(args: Array[String]): Unit = {
val car1 = new Car()
// car1.speed // 错误:私有成员不能在类外部访问
car1.run() // 速度为: 0, run...
val engine = new car1.Engine()
engine.acc(10) // 内部类修改外部类的私有成员
car1.run() // 速度为: 10, run...
val park = new car1.AutoPark()
park.park() // 自动泊车完成,速度归零
car1.run() // 速度为: 0, run...
println(s"通过引擎获取速度: ${engine.getSpeed()}")
}
}
关键特性验证:
✅ 内部类可以直接访问外部类的私有成员
speed(私有变量)fuel(私有变量)maxSpeed(私有常量)
✅ 多个内部类可以访问同一个外部类实例的成员
Engine、FuelSystem、AirCondition都操作同一个Car实例
✅ 内部类之间可以通过外部类实例间接交互
- 空调影响燃油消耗
- 燃油系统可以紧急制动
这充分证明了内部类与外部类实例的紧密关联性!
(五)匿名类
匿名类指没有名字的类。匿名类只能使用一次。