HarmonyOS Next类设计实战:从对象建模到生命周期管理

还记得第一次写设备类时,因为继承顺序搞错导致系统崩溃,Debug两小时才发现是构造函数没调super()。今天把这些年踩过的坑和总结的类设计经验分享出来,帮大家少走弯路。

一、类的本质:数据与行为的「集装箱」

1.1 成员定义的避坑指南

// 智能家居设备基类(正确示范)
open class SmartDevice {
    public var deviceId: String     // 设备唯一标识
        private var _status: DeviceStatus = .offline  // 用下划线标记私有变量
            
                // 主构造函数,参数直接声明为成员
                    public SmartDevice(id: String) {
                            self.deviceId = id
                                }
                                    
                                        // 状态访问器(带验证逻辑)
                                            public func getStatus() -> DeviceStatus {
                                                    _status
                                                        }
                                                            
                                                                public func setStatus(status: DeviceStatus) {
                                                                        if status == .online && _status == .offline {
                                                                                    logStatusChange() // 状态变更日志
                                                                                            }
                                                                                                    _status = status
                                                                                                        }
                                                                                                        }
                                                                                                        ```
**血泪教训**:曾把所有变量设为public,导致外部直接修改状态引发异常,后来用getter/setter封装验证逻辑,bug减少60%。  


## 二、生命周期:对象的「诞生到消亡」之旅  

### 2.1 构造函数的执行顺序  
```cj
class Parent {
    public var parentProp: String
        
            public Parent(prop: String) {
                    parentProp = prop
                            printInitMsg() // 此时子类尚未初始化
                                }
                                    
                                        public open func printInitMsg() {
                                                println("Parent initialized")
                                                    }
                                                    }
class Child <: Parent {
    public var childProp: Int
        
            public Child(prop: String, childProp: Int) {
                    self.childProp = childProp
                            super.init(prop: prop) // 必须先调用父类构造
                                }
                                    
                                        public override func printInitMsg() {
                                                println("Child initialized with: \(childProp)")
                                                    }
                                                    }
// 执行Child("test", 10)时,输出:
// Parent initialized (父类先执行,此时childProp为0)
// 正确做法:避免在父类构造中调用子类重写的方法

2.2 终结器的正确打开方式

class NativeResource {
    private var ptr: UnsafeRawPointer?
        
            init(size: Int) {
                    ptr = malloc(size) // 分配C内存
                        }
                            
                                ~init() {
                                        if let p = ptr {
                                                    free(p) // 终结器释放资源
                                                                ptr = nil
                                                                        }
                                                                            }
                                                                                
                                                                                    // 手动释放方法(比终结器更可控)
                                                                                        public func release() {
                                                                                                if let p = ptr {
                                                                                                            free(p)
                                                                                                                        ptr = nil
                                                                                                                                }
                                                                                                                                    }
                                                                                                                                    }
                                                                                                                                    ```
**性能提示**:终结器是最后的保障,最好提供手动释放方法,在不依赖GC时主动释放资源。  


## 三、继承机制:代码复用的「双刃剑」  

### 3.1 抽象类与模板方法模式  
```cj
// 设备控制抽象类(模板方法)
abstract class DeviceController {
    public func control(device: SmartDevice) {
            preCheck()          // 通用前置检查
                    doControl(device)   // 抽象方法,子类实现
                            postCheck()         // 通用后置检查
                                }
                                    
                                        protected func preCheck() { /* 权限验证等通用逻辑 */ }
                                            protected abstract func doControl(device: SmartDevice)
                                                protected func postCheck() { /* 日志记录等通用逻辑 */ }
                                                }
// 灯泡控制实现
class BulbController <: DeviceController {
    protected override func doControl(device: SmartDevice) {
            if let bulb = device as? SmartBulb {
                        bulb.turnOn()
                                }
                                    }
                                    }
                                    ```
### 3.2 组合优于继承的场景  
```cj
// 错误做法:继承导致功能膨胀
class CameraDevice <: SmartDevice {
    // 包含拍照、录像、对焦等功能
    }
// 正确做法:组合功能接口
class CameraDevice <: SmartDevice {
    private let captureHandler: CaptureHandler   // 组合拍照功能
        private let focusHandler: FocusHandler     // 组合对焦功能
            
                public func takePhoto() {
                        captureHandler.shot()
                                focusHandler.autoFocus()
                                    }
                                    }
                                    ```

## 四、实战:智能家居类的演进之路  

### 4.1 初代设计(问题百出)  
```cj
// 最初版:所有设备共用一个类
class SmartDevice {
    var type: DeviceType
        var status: DeviceStatus
            // 包含所有设备的通用逻辑和特有逻辑
            }
            ```
**问题**:  
- 新增设备类型时需修改类定义  
- - 特有功能混杂,代码混乱  

### 4.2 重构后架构(清晰可扩展)  
```cj
// 基类
open class SmartDevice { /* 通用属性和方法 */ }

// 接口定义特有能力
interface Cameraable { func takePhoto() }
interface Speakerable { func playSound() }

// 具体设备类(组合接口)
class SmartCamera <: SmartDevice, Cameraable {
    public func takePhoto() { /* 拍照实现 */ }
    }
class SmartSpeaker <: SmartDevice, Speakerable {
    public func playSound() { /* 播放实现 */ }
    }
    ```
**优化效果**:  
- 新增设备类型时无需修改基类  
- - 功能职责清晰,维护成本降70%  

## 五、必知陷阱与最佳实践  

1. **初始化顺序陷阱**:  
2.    父类构造中不要调用子类重写的方法,可能访问未初始化成员  
3. **终结器性能问题**:  
4.    避免在终结器中执行网络请求等耗时操作,可能导致GC停顿  
5. **继承深度控制**:  
6.    继承层级控制在3层以内,超过则考虑重构为组合模式  
7. 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值