
回复
在HarmonyOS Next开发中,属性(Property)是实现数据封装与行为抽象的核心机制。通过属性的getter
和setter
,开发者能够在不暴露内部实现的前提下,灵活控制数据的读取与修改。本文结合《仓颉编程语言开发指南》,解析属性的高级应用场景与最佳实践。
属性通过prop
关键字声明,将数据访问逻辑与存储解耦。与成员变量不同,属性不直接存储值,而是通过自定义逻辑控制读写。
class TemperatureSensor {
private var _temp: Float64 = 25.0
private let minTemp: Float64 = -20.0
private let maxTemp: Float64 = 80.0
// 只读属性:暴露温度值,限制修改
public prop temperature: Float64 {
get() { _temp }
}
// 读写属性:验证温度范围
public mut prop targetTemperature: Float64 {
get() { _temp }
set(value) {
if value >= minTemp && value <= maxTemp {
_temp = value
} else {
throw Error("温度超出范围:\(value)")
}
}
}
}
对于简单逻辑,可省略get
关键字,直接返回表达式:
class Circle {
private let radius: Float64
public prop area: Float64 = 3.14 * radius * radius // 隐式getter
public init(radius: Float64) { self.radius = radius }
}
静态属性属于类本身,而非实例,通过static
修饰:
class AppConfig {
public static prop appVersion: String {
get() { "1.2.3" }
}
public static mut prop debugMode: Bool {
get() { false }
set { /* 写入逻辑 */ }
}
}
// 使用示例
println(AppConfig.appVersion) // 输出:1.2.3
AppConfig.debugMode = true
通过didSet
和willSet
钩子函数,监听属性值变化:
class User {
public mut prop email: String {
didSet {
if email != oldValue { // oldValue为旧值
sendNotification("邮箱已变更为:\(email)")
}
}
}
}
接口可声明抽象属性,强制实现类提供读写逻辑:
interface Observable {
mut prop data: String // 抽象读写属性
prop version: Int // 抽象只读属性
}
class DataModel <: Observable {
private var _data: String = ""
private var _version: Int = 0
public mut prop data: String {
get() { _data }
set { _data = value; _version += 1 }
}
public prop version: Int { get() { _version } }
}
属性可通过访问修饰符(public
/private
等)控制可见性:
class SecureStorage {
private mut prop encryptionKey: String {
get() { loadKey() }
set { saveKey(newValue) }
}
public func getDecryptedData() -> String {
// 内部使用私有属性
let key = encryptionKey
// 解密逻辑
}
}
子类可覆盖父类属性,需保持类型一致并使用override
修饰:
open class Base {
public open mut prop value: Int = 0
}
class Derived <: Base {
public override mut prop value: Int {
get() { super.value * 2 } // 读取时放大两倍
set { super.value = newValue / 2 } // 写入时缩小两倍
}
}
属性可在类型转换中发挥作用,例如接口属性的动态访问:
interface Measurable {
prop value: Float64
}
class Thermometer <: Measurable {
public prop value: Float64 = 25.0
}
let device: Any = Thermometer()
if let measurable = device as? Measurable {
println("测量值:\(measurable.value)") // 动态访问属性
}
abstract class DeviceParam<T> {
public abstract mut prop value: T // 抽象读写属性
public prop history: [T] = []
protected func logChange(oldValue: T, newValue: T) {
history.append(newValue)
syncToCloud(oldValue, newValue) // 抽象函数,子类实现
}
protected abstract func syncToCloud(oldValue: T, newValue: T)
}
class TemperatureParam <: DeviceParam<Float64> {
private var _value: Float64 = 25.0
public override mut prop value: Float64 {
get() { _value }
set {
if newValue >= -40.0 && newValue <= 125.0 { // 温度范围校验
let oldValue = _value
_value = newValue
logChange(oldValue: oldValue, newValue: newValue)
} else {
throw Error("温度参数无效:\(newValue)")
}
}
}
protected override func syncToCloud(oldValue: Float64, newValue: Float64) {
// 实现网络同步逻辑
println("同步温度变更:\(oldValue) → \(newValue)")
}
}
let tempParam = TemperatureParam()
tempParam.value = 28.5 // 触发校验、日志记录与同步
println("历史记录:\(tempParam.history)") // 输出:[28.5]
func updateParam(param: DeviceParam<Float64>, newValue: Float64) {
param.value = newValue // 多态调用,自动适配具体参数逻辑
}
在getter
/setter
中避免直接或间接调用自身,防止死循环:
class Counter {
private var _count: Int = 0
public mut prop count: Int {
get() { count + 1 } // 递归调用getter,导致栈溢出
set { _count = newValue }
}
}
公共变量破坏封装性,属性可灵活添加验证逻辑:
// 反例:直接暴露公共变量
class BadDesign {
public var volume: Int = 0 // 无限制修改
}
// 正例:通过属性限制音量范围
class GoodDesign {
public mut prop volume: Int {
set { volume = max(0, min(100, newValue)) }
}
}
多线程环境下需确保静态属性访问的线程安全,可通过互斥锁实现:
class ThreadSafeConfig {
private static var _instance: ThreadSafeConfig?
private static var lock = Mutex()
public static prop instance: ThreadSafeConfig {
get() {
lock.lock()
defer { lock.unlock() }
return _instance ?? createNewInstance()
}
}
}
HarmonyOS Next的属性机制体现了“数据即接口”的设计思想:
getter
/setter
提供统一访问入口;