Skip to content

程序结构

概述

本章介绍Kotlin程序的组织结构,包括包、文件、类、对象、接口等核心概念。理解这些结构有助于编写组织良好、可维护的Kotlin代码。

包结构

包声明

kotlin
// 文件:src/main/kotlin/com/example/myapp/models/User.kt
package com.example.myapp.models

class User(val name: String, val email: String)

包的组织原则

kotlin
// 按功能组织包结构
com.example.myapp/
├── models/          // 数据模型
│   ├── User.kt
│   ├── Product.kt
│   └── Order.kt
├── services/        // 业务逻辑
│   ├── UserService.kt
│   └── OrderService.kt
├── repositories/    // 数据访问
│   ├── UserRepository.kt
│   └── OrderRepository.kt
├── controllers/     // 控制器(Web应用)
│   └── UserController.kt
└── utils/          // 工具类
    ├── DateUtils.kt
    └── StringUtils.kt

顶级声明

kotlin
// 文件:MathUtils.kt
package com.example.utils

// 顶级函数
fun calculateArea(radius: Double): Double = Math.PI * radius * radius

// 顶级属性
const val PI_APPROXIMATION = 3.14159

// 顶级类
class Calculator {
    fun add(a: Int, b: Int) = a + b
}

// 顶级对象
object MathConstants {
    const val E = 2.71828
    const val GOLDEN_RATIO = 1.61803
}

类结构

基本类定义

kotlin
// 简单类
class Person {
    // 属性
    var name: String = ""
    var age: Int = 0
    
    // 方法
    fun introduce() {
        println("Hi, I'm $name, $age years old")
    }
}

// 带主构造函数的类
class Student(val name: String, val studentId: String) {
    // 次构造函数
    constructor(name: String, studentId: String, grade: Int) : this(name, studentId) {
        this.grade = grade
    }
    
    // 属性
    var grade: Int = 1
    
    // 初始化块
    init {
        println("Student $name created with ID $studentId")
    }
    
    // 方法
    fun study(subject: String) {
        println("$name is studying $subject")
    }
}

类的可见性修饰符

kotlin
// 默认是public
class PublicClass

// 内部可见(同一模块)
internal class InternalClass

// 私有类(同一文件)
private class PrivateClass

class Example {
    // 公共属性
    val publicProperty = "public"
    
    // 内部属性
    internal val internalProperty = "internal"
    
    // 保护属性(子类可见)
    protected val protectedProperty = "protected"
    
    // 私有属性
    private val privateProperty = "private"
    
    // 公共方法
    fun publicMethod() {}
    
    // 私有方法
    private fun privateMethod() {}
}

接口

接口定义和实现

kotlin
// 接口定义
interface Drawable {
    // 抽象属性
    val color: String
    
    // 抽象方法
    fun draw()
    
    // 带默认实现的方法
    fun getInfo(): String = "Drawable object with color $color"
    
    // 带默认实现的属性
    val isVisible: Boolean
        get() = true
}

// 实现接口
class Circle(override val color: String, val radius: Double) : Drawable {
    override fun draw() {
        println("Drawing a $color circle with radius $radius")
    }
    
    override fun getInfo(): String {
        return "Circle: ${super.getInfo()}, radius=$radius"
    }
}

// 多接口实现
interface Movable {
    fun move(x: Int, y: Int)
}

class MovableCircle(
    override val color: String,
    val radius: Double
) : Drawable, Movable {
    private var x = 0
    private var y = 0
    
    override fun draw() {
        println("Drawing circle at ($x, $y)")
    }
    
    override fun move(x: Int, y: Int) {
        this.x = x
        this.y = y
    }
}

函数式接口 (SAM)

kotlin
// 函数式接口
fun interface StringProcessor {
    fun process(input: String): String
}

// 使用lambda实现
fun main() {
    val upperCaseProcessor = StringProcessor { it.uppercase() }
    val result = upperCaseProcessor.process("hello")
    println(result)  // HELLO
    
    // 直接传递lambda
    processString("world") { it.reversed() }
}

fun processString(input: String, processor: StringProcessor): String {
    return processor.process(input)
}

对象声明和表达式

对象声明 (Singleton)

kotlin
// 单例对象
object DatabaseManager {
    private var isConnected = false
    
    fun connect() {
        if (!isConnected) {
            println("Connecting to database...")
            isConnected = true
        }
    }
    
    fun disconnect() {
        if (isConnected) {
            println("Disconnecting from database...")
            isConnected = false
        }
    }
    
    fun isConnected() = isConnected
}

// 使用单例对象
fun main() {
    DatabaseManager.connect()
    println("Connected: ${DatabaseManager.isConnected()}")
    DatabaseManager.disconnect()
}

伴生对象

kotlin
class User private constructor(val name: String, val email: String) {
    companion object Factory {
        private var userCount = 0
        
        // 工厂方法
        fun createUser(name: String, email: String): User {
            userCount++
            return User(name, email)
        }
        
        fun createGuestUser(): User {
            return createUser("Guest", "guest@example.com")
        }
        
        // 伴生对象属性
        fun getUserCount() = userCount
    }
    
    override fun toString() = "User(name='$name', email='$email')"
}

fun main() {
    val user1 = User.createUser("Alice", "alice@example.com")
    val user2 = User.createGuestUser()
    
    println("Users created: ${User.getUserCount()}")
    println(user1)
    println(user2)
}

对象表达式 (匿名对象)

kotlin
interface ClickListener {
    fun onClick()
    fun onLongClick()
}

fun main() {
    // 匿名对象实现接口
    val button = object : ClickListener {
        override fun onClick() {
            println("Button clicked")
        }
        
        override fun onLongClick() {
            println("Button long clicked")
        }
    }
    
    button.onClick()
    button.onLongClick()
    
    // 匿名对象继承类
    val customList = object : ArrayList<String>() {
        override fun add(element: String): Boolean {
            println("Adding element: $element")
            return super.add(element)
        }
    }
    
    customList.add("Hello")
    customList.add("World")
}

枚举类

基本枚举

kotlin
enum class Direction {
    NORTH, SOUTH, EAST, WEST
}

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF),
    YELLOW(0xFFFF00);
    
    fun getHexString(): String = "#${rgb.toString(16).padStart(6, '0')}"
}

fun main() {
    // 使用枚举
    val direction = Direction.NORTH
    println("Direction: $direction")
    
    // 枚举属性和方法
    val red = Color.RED
    println("Red RGB: ${red.rgb}")
    println("Red Hex: ${red.getHexString()}")
    
    // 枚举遍历
    println("All colors:")
    for (color in Color.values()) {
        println("${color.name}: ${color.getHexString()}")
    }
}

枚举的高级特性

kotlin
enum class Planet(val mass: Double, val radius: Double) {
    MERCURY(3.303e+23, 2.4397e6),
    VENUS(4.869e+24, 6.0518e6),
    EARTH(5.976e+24, 6.37814e6),
    MARS(6.421e+23, 3.3972e6);
    
    // 枚举类中的方法
    fun surfaceGravity(): Double {
        val G = 6.67300E-11
        return G * mass / (radius * radius)
    }
    
    fun surfaceWeight(otherMass: Double): Double {
        return otherMass * surfaceGravity()
    }
    
    companion object {
        fun findByMass(mass: Double): Planet? {
            return values().find { it.mass == mass }
        }
    }
}

fun main() {
    val earthWeight = 175.0
    val mass = earthWeight / Planet.EARTH.surfaceGravity()
    
    println("Weight on different planets:")
    for (planet in Planet.values()) {
        val weight = planet.surfaceWeight(mass)
        println("${planet.name}: %.2f".format(weight))
    }
}

密封类

密封类定义

kotlin
// 密封类表示受限的类层次结构
sealed class Result<out T>

data class Success<T>(val data: T) : Result<T>()
data class Error(val exception: Throwable) : Result<Nothing>()
object Loading : Result<Nothing>()

// 使用密封类
fun handleResult(result: Result<String>) {
    when (result) {
        is Success -> println("Success: ${result.data}")
        is Error -> println("Error: ${result.exception.message}")
        Loading -> println("Loading...")
        // 不需要else分支,编译器知道所有可能的子类
    }
}

fun main() {
    val results = listOf(
        Success("Data loaded successfully"),
        Error(RuntimeException("Network error")),
        Loading
    )
    
    results.forEach { handleResult(it) }
}

密封接口

kotlin
sealed interface UIEvent

data class ButtonClick(val buttonId: String) : UIEvent
data class TextInput(val text: String) : UIEvent
object ScreenLoad : UIEvent

class UIEventHandler {
    fun handle(event: UIEvent) {
        when (event) {
            is ButtonClick -> println("Button ${event.buttonId} clicked")
            is TextInput -> println("Text entered: ${event.text}")
            ScreenLoad -> println("Screen loaded")
        }
    }
}

数据类

数据类定义

kotlin
// 数据类自动生成equals, hashCode, toString, copy等方法
data class Person(
    val name: String,
    val age: Int,
    val email: String
) {
    // 数据类也可以有自定义方法
    fun isAdult(): Boolean = age >= 18
    
    // 数据类可以有次构造函数
    constructor(name: String, age: Int) : this(name, age, "")
}

fun main() {
    val person1 = Person("Alice", 25, "alice@example.com")
    val person2 = Person("Alice", 25, "alice@example.com")
    val person3 = person1.copy(age = 26)  // 复制并修改
    
    // 自动生成的方法
    println("person1 == person2: ${person1 == person2}")  // true
    println("person1: $person1")  // 自动生成的toString
    
    // 解构声明
    val (name, age, email) = person1
    println("Name: $name, Age: $age, Email: $email")
    
    // 自定义方法
    println("Is adult: ${person1.isAdult()}")
}

内联类 (Value Classes)

kotlin
// 内联类提供类型安全的包装,没有运行时开销
@JvmInline
value class UserId(val value: String)

@JvmInline
value class Email(val value: String) {
    init {
        require(value.contains("@")) { "Invalid email format" }
    }
    
    fun getDomain(): String = value.substringAfter("@")
}

fun processUser(userId: UserId, email: Email) {
    println("Processing user ${userId.value} with email ${email.value}")
    println("Email domain: ${email.getDomain()}")
}

fun main() {
    val userId = UserId("user123")
    val email = Email("user@example.com")
    
    processUser(userId, email)
    
    // 类型安全:不能混淆参数
    // processUser(email, userId)  // 编译错误
}

嵌套类和内部类

嵌套类

kotlin
class Outer {
    private val outerProperty = "Outer property"
    
    // 嵌套类(静态)
    class Nested {
        fun doSomething() {
            println("Nested class method")
            // println(outerProperty)  // 编译错误:无法访问外部类成员
        }
    }
    
    // 内部类
    inner class Inner {
        fun doSomething() {
            println("Inner class method")
            println("Accessing: $outerProperty")  // 可以访问外部类成员
        }
    }
}

fun main() {
    // 创建嵌套类实例
    val nested = Outer.Nested()
    nested.doSomething()
    
    // 创建内部类实例
    val outer = Outer()
    val inner = outer.Inner()
    inner.doSomething()
}

扩展

扩展函数

kotlin
// 为String类添加扩展函数
fun String.isPalindrome(): Boolean {
    val cleaned = this.lowercase().replace(" ", "")
    return cleaned == cleaned.reversed()
}

// 为List添加扩展函数
fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null

// 扩展属性
val String.wordCount: Int
    get() = this.split("\\s+".toRegex()).size

fun main() {
    val text = "A man a plan a canal Panama"
    println("'$text' is palindrome: ${text.isPalindrome()}")
    println("Word count: ${text.wordCount}")
    
    val numbers = listOf(1, 2, 3, 4, 5)
    println("Second element: ${numbers.secondOrNull()}")
}

扩展的作用域

kotlin
class Host(val hostname: String) {
    fun printHostname() { print(hostname) }
}

class Connection(val host: Host, val port: Int) {
    fun printPort() { print(port) }
    
    fun Host.printConnectionString() {
        printHostname()   // 调用Host.printHostname()
        print(":")
        printPort()       // 调用Connection.printPort()
    }
    
    fun connect() {
        host.printConnectionString()  // 调用扩展函数
    }
}

fun main() {
    Connection(Host("kotl.in"), 443).connect()
}

委托

类委托

kotlin
interface Base {
    fun print()
    fun printMessage(message: String)
}

class BaseImpl(val x: Int) : Base {
    override fun print() { println("BaseImpl: $x") }
    override fun printMessage(message: String) { println("BaseImpl: $message") }
}

// 委托给另一个对象
class Derived(b: Base) : Base by b {
    // 可以重写委托的方法
    override fun printMessage(message: String) {
        println("Derived: $message")
    }
}

fun main() {
    val base = BaseImpl(42)
    val derived = Derived(base)
    
    derived.print()  // 委托给BaseImpl
    derived.printMessage("Hello")  // 使用重写的方法
}

最佳实践

1. 包组织

kotlin
// 按功能而非技术层面组织包
// 好的组织方式
com.example.ecommerce/
├── user/
├── product/
├── order/
└── payment/

// 避免的组织方式
com.example.ecommerce/
├── controllers/
├── services/
├── repositories/
└── models/

2. 类设计

kotlin
// 优先使用数据类
data class User(val id: Long, val name: String, val email: String)

// 使用密封类表示状态
sealed class LoadingState {
    object Loading : LoadingState()
    data class Success(val data: String) : LoadingState()
    data class Error(val message: String) : LoadingState()
}

// 使用对象声明实现单例
object ConfigManager {
    fun getConfig(key: String): String? = TODO()
}

3. 可见性

kotlin
class ApiClient {
    // 公开必要的接口
    fun fetchData(): String = processRequest()
    
    // 隐藏实现细节
    private fun processRequest(): String = TODO()
    
    // 使用internal限制模块内访问
    internal fun debugInfo(): String = TODO()
}

下一步

了解了程序结构后,让我们深入学习Kotlin的数据类型系统。

下一章: 数据类型

练习题

  1. 创建一个包含多个包的项目结构
  2. 实现一个使用接口和实现类的图形绘制系统
  3. 设计一个使用密封类表示不同状态的网络请求结果
  4. 创建一个使用伴生对象的工厂模式示例
  5. 实现一个使用扩展函数增强现有类功能的工具库

本站内容仅供学习和研究使用。