Kotlin override abstract 抽象类

Kotlin · 22 天前 · 9 人浏览

在 Kotlin 中,override abstract 只能出现在抽象类 (abstract class) 或接口 (interface) 中。它的作用是强制子类实现一个继承来的抽象方法


1. override abstract 属于抽象类(abstract class

  • override abstract 主要用于 继承父类的方法,但不提供实现,强制子类实现
  • override 说明它是 重写 父类的方法。
  • abstract 说明它 本身没有实现,要求子类必须实现

示例

open class Base {
    open fun f() {}  // 可被子类重写
}

abstract class Derived : Base() {
    override abstract fun f()  // 继承了 Base,但不提供实现,子类必须实现
}

class ConcreteDerived : Derived() {
    override fun f() {
        println("ConcreteDerived 实现了 f()")
    }
}

fun main() {
    val obj = ConcreteDerived()
    obj.f()  // 输出 "ConcreteDerived 实现了 f()"
}

解释:

  • Base 是一个普通的 open 类,f() 方法是可重写的。
  • Derived 继承 Base,但 override abstract fun f() 不提供实现,强制其子类 ConcreteDerived 必须实现 f()

2. override abstract 适用于接口(interface

  • 在接口 (interface) 中,所有方法默认都是 abstract,所以 abstract 关键字是多余的,不需要写。
  • 但如果 interface 继承了另一个 interface,可以使用 override 来重写方法,并保持 abstract 让子类去实现。

示例

interface BaseInterface {
    fun f()
}

interface DerivedInterface : BaseInterface {
    override fun f()  // 仍然是抽象方法,子类必须实现
}

class ConcreteClass : DerivedInterface {
    override fun f() {
        println("ConcreteClass 实现了 f()")
    }
}

fun main() {
    val obj = ConcreteClass()
    obj.f()  // 输出 "ConcreteClass 实现了 f()"
}

解释:

  • BaseInterface 定义了 f(),但没有实现(默认 abstract)。
  • DerivedInterface 继承 BaseInterface,但仍然不实现 f(),保持抽象,强制子类 ConcreteClass 实现 f()

3. override abstract 不能用于普通类

如果 Base 不是 openabstract,就不能使用 override abstract

错误示例

class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()  // ❌ 错误:Base 不是 open/abstract,不能 override abstract
}

错误原因:

  • Base 不是 open,所以 f() 不能被 override
  • override abstract 只能在 继承了 openabstract 类的方法时 使用。

4. 结论

关键字适用类型作用
open普通类 (class)允许类或方法被继承/重写
abstract抽象类 (abstract class) 或接口 (interface)不能实例化,方法无实现,子类必须实现
override子类重写父类的 openabstract 方法
override abstract继承自 openabstract 类的抽象类强制子类实现方法,不提供实现

override abstract 只能用于:

  1. 继承自 open classabstract class 的抽象类
  2. 继承自 interface 的接口(但 abstract 省略)

“强制子类实现方法” 的一种策略,广泛应用在 框架设计、模板方法模式、抽象业务逻辑、强制接口实现等场景


1. 场景:框架设计

如果你在开发一个库,希望提供一套标准接口,要求所有子类都必须实现某个方法,就可以用 override abstract

示例:网络请求框架

假设我们在做一个网络请求框架,支持 HTTPWebSocket,但每种方式的请求逻辑不同。
我们用 abstract class 作为中间层,强制子类实现 sendRequest()

// 基类:定义通用逻辑
open class NetworkClient {
    open fun connect() {
        println("Connecting to network...")
    }
}

// 抽象类:定义抽象方法,不允许默认实现
abstract class RequestHandler : NetworkClient() {
    override abstract fun sendRequest(data: String)
}

// HTTP 请求子类
class HttpRequestHandler : RequestHandler() {
    override fun sendRequest(data: String) {
        println("Sending HTTP request: $data")
    }
}

// WebSocket 请求子类
class WebSocketRequestHandler : RequestHandler() {
    override fun sendRequest(data: String) {
        println("Sending WebSocket request: $data")
    }
}

fun main() {
    val httpHandler = HttpRequestHandler()
    httpHandler.connect()  // "Connecting to network..."
    httpHandler.sendRequest("GET /home")  // "Sending HTTP request: GET /home"

    val wsHandler = WebSocketRequestHandler()
    wsHandler.connect()
    wsHandler.sendRequest("Hello WebSocket")  // "Sending WebSocket request: Hello WebSocket"
}

为什么要用 override abstract

  • connect() 方法在 NetworkClient 中有默认实现,所有子类都可以直接调用。
  • sendRequest()RequestHandler 中是抽象方法强制子类实现,这样我们确保 HttpRequestHandlerWebSocketRequestHandler 必须定义自己的请求逻辑。

2. 场景:模板方法模式(Template Method Pattern)

适用于部分逻辑通用、部分逻辑需要子类实现的情况。

示例:文档处理

假设我们有一个处理文档的系统:

  • 加载文件(所有文档格式通用)
  • 解析文件内容(每种格式不同,比如 PDF 和 Word)
  • 关闭文件(所有文档格式通用)

可以这样设计:

abstract class DocumentProcessor {
    fun processDocument() {
        openFile()
        parseContent()
        closeFile()
    }

    private fun openFile() {
        println("Opening file...")
    }

    abstract fun parseContent()  // 让子类必须实现

    private fun closeFile() {
        println("Closing file.")
    }
}

// PDF 解析器
class PDFProcessor : DocumentProcessor() {
    override fun parseContent() {
        println("Parsing PDF content...")
    }
}

// Word 解析器
class WordProcessor : DocumentProcessor() {
    override fun parseContent() {
        println("Parsing Word content...")
    }
}

fun main() {
    val pdf = PDFProcessor()
    pdf.processDocument()
    // Output:
    // Opening file...
    // Parsing PDF content...
    // Closing file.

    val word = WordProcessor()
    word.processDocument()
    // Output:
    // Opening file...
    // Parsing Word content...
    // Closing file.
}

为什么要用 override abstract

  • openFile()closeFile() 是通用的,所有子类共享。
  • parseContent()抽象方法,强制子类实现不同的解析方式。

3. 场景:业务逻辑抽象

当你的系统有不同的业务场景,但它们有一些相同的流程时,可以用 override abstract 强制子类实现关键方法

示例:支付系统

假设我们要开发一个支付系统,支持 微信支付支付宝支付
流程是:

  1. 选择支付方式
  2. 执行支付逻辑(不同支付方式不同)
  3. 记录支付日志
abstract class PaymentProcessor {
    fun processPayment(amount: Double) {
        selectPaymentMethod()
        executePayment(amount)  // 这个方法必须由子类实现
        logPayment(amount)
    }

    private fun selectPaymentMethod() {
        println("Selecting payment method...")
    }

    abstract fun executePayment(amount: Double)

    private fun logPayment(amount: Double) {
        println("Logging payment of $$amount")
    }
}

// 微信支付
class WeChatPay : PaymentProcessor() {
    override fun executePayment(amount: Double) {
        println("Processing WeChat Pay of $$amount")
    }
}

// 支付宝支付
class AliPay : PaymentProcessor() {
    override fun executePayment(amount: Double) {
        println("Processing AliPay of $$amount")
    }
}

fun main() {
    val weChatPay = WeChatPay()
    weChatPay.processPayment(100.0)
    // Output:
    // Selecting payment method...
    // Processing WeChat Pay of $100.0
    // Logging payment of $100.0

    val aliPay = AliPay()
    aliPay.processPayment(200.0)
    // Output:
    // Selecting payment method...
    // Processing AliPay of $200.0
    // Logging payment of $200.0
}

为什么要用 override abstract

  • selectPaymentMethod()logPayment() 对所有支付方式通用。
  • executePayment() 必须由子类实现,确保每种支付方式的逻辑不同。

4. 场景:强制子类实现某些功能

当你有一个类层级,想要强制子类提供实现,可以用 override abstract

示例:日志系统

open class Logger {
    open fun log(message: String) {
        println("Default log: $message")
    }
}

abstract class CustomLogger : Logger() {
    override abstract fun log(message: String)
}

// 具体实现:文件日志
class FileLogger : CustomLogger() {
    override fun log(message: String) {
        println("Writing log to file: $message")
    }
}

// 具体实现:控制台日志
class ConsoleLogger : CustomLogger() {
    override fun log(message: String) {
        println("Logging to console: $message")
    }
}

fun main() {
    val fileLogger = FileLogger()
    fileLogger.log("File log test")  // 输出:Writing log to file: File log test

    val consoleLogger = ConsoleLogger()
    consoleLogger.log("Console log test")  // 输出:Logging to console: Console log test
}

为什么要用 override abstract

  • CustomLogger 不允许使用 Logger 默认实现,强制子类实现自己的日志逻辑

总结

场景作用
网络请求框架确保所有请求类型必须实现 sendRequest()
模板方法模式共享通用逻辑,强制子类实现关键方法
支付系统强制不同支付方式实现 executePayment()
日志系统确保不同日志方式实现 log()

核心思想:
1. 让部分逻辑通用(比如 processPayment())。
2. 让子类必须实现关键方法(比如 executePayment())。

如果你正在设计 框架、业务逻辑、或者想强制子类实现某些功能override abstract 非常有用!🚀

本站立足于美利堅合衆國,請讀者自覺遵守當地法律!如有違規,本站不承擔任何法律責任! This site is based in the United States of America, readers are requested to abide by local laws! If there are any violations, this site does not bear any legal responsibility! Theme Jasmine by Kent Liao