Swift中结构体默认成员语法糖及代码兼容实现方案问询
解决方案:用Swift协议实现无缝替换
要实现Stringish从String别名切换到带value和version的StringBonus结构体,同时保留原有代码的语法习惯,可以通过以下Swift语言特性组合实现:
核心实现步骤
1. 让结构体支持字符串字面量赋值
通过实现ExpressibleByStringLiteral协议,让StringBonus可以直接接收字符串赋值(比如x = "yo"):
struct StringBonus { var value: String var version: Int = 1 // 默认版本号 // 支持字符串字面量初始化 init(stringLiteral value: StringLiteralType) { self.value = value } }
这样原有代码里直接给StringBonus类型变量赋值字符串的逻辑完全不用修改。
2. 保留对String原有方法/属性的直接访问
如果原有代码里有类似x.count、x.hasPrefix("test")这类调用String属性/方法的逻辑,不用改成x.value.count,可以通过@dynamicMemberLookup把这些调用自动转发到value字段:
@dynamicMemberLookup struct StringBonus { var value: String var version: Int = 1 init(stringLiteral value: StringLiteralType) { self.value = value } // 动态转发成员访问到value属性 subscript<T>(dynamicMember keyPath: KeyPath<String, T>) -> T { value[keyPath: keyPath] } // 可变成员的转发(比如修改value的某个可变属性) subscript<T>(dynamicMember keyPath: WritableKeyPath<String, T>) -> T { get { value[keyPath: keyPath] } set { value[keyPath: keyPath] = newValue } } }
现在你可以直接写print(x.count),底层会自动调用x.value.count,完全兼容原有代码。
3. 支持字符串操作符(如+=、+)
如果原有代码用了字符串拼接操作,需要为StringBonus实现对应的操作符重载:
// 重载+=操作符 extension StringBonus { static func += (lhs: inout StringBonus, rhs: String) { lhs.value += rhs } // 重载+操作符,返回新的StringBonus实例 static func + (lhs: StringBonus, rhs: String) -> StringBonus { var newInstance = lhs newInstance.value += rhs return newInstance } }
这样x += "suffix"这类代码也能正常工作。
关于@resultBuilder的说明
@resultBuilder主要用于构建结构化的结果(比如SwiftUI视图、DSL语法),对于你当前的需求——让结构体兼容String的赋值和成员访问——完全用不上,没必要引入这个特性。
完整示例代码
@dynamicMemberLookup struct StringBonus { var value: String var version: Int = 1 init(stringLiteral value: StringLiteralType) { self.value = value } subscript<T>(dynamicMember keyPath: KeyPath<String, T>) -> T { value[keyPath: keyPath] } subscript<T>(dynamicMember keyPath: WritableKeyPath<String, T>) -> T { get { value[keyPath: keyPath] } set { value[keyPath: keyPath] = newValue } } } extension StringBonus { static func += (lhs: inout StringBonus, rhs: String) { lhs.value += rhs } static func + (lhs: StringBonus, rhs: String) -> StringBonus { var newInstance = lhs newInstance.value += rhs return newInstance } } // 测试代码 var x: StringBonus = "yo" print(x.value) // 输出 "yo" print(x.count) // 输出 2,自动转发到value.count x.version = 2 print(x.version) // 输出 2 x += " test" print(x.value) // 输出 "yo test"
内容的提问来源于stack exchange,提问作者Fattie
相关产品推荐
相关产品推荐

