Swift是否有类似Java AutoValue的自动生成Hashable实现的功能?
Great question! In Swift, we have both built-in compiler features and third-party libraries that mirror the functionality of Java's AutoValue—specifically for automatically generating and maintaining Hashable (and Equatable) implementations as you add or modify fields. Let's break down the options:
一、Swift 内置自动合成(推荐,零额外依赖)
Starting with Swift 4, the compiler will automatically synthesize Equatable and Hashable implementations for your structs (and final classes, with a small caveat) as long as all stored properties conform to Equatable and Hashable. This means you never have to manually write == operators or hash(into:) methods, and any new fields you add will be automatically included in these implementations.
Example with a struct
// No manual implementation needed—compiler handles everything struct PlainStruct: Hashable { let id: Int let name: String let timestamp: Date } // If you add a new field later, the compiler updates Hashable/Equatable automatically struct PlainStruct: Hashable { let id: Int let name: String let timestamp: Date let isActive: Bool // New field, no extra code required }
Example with a final class
For classes, you need to explicitly declare conformance to the protocols, but the compiler still handles the implementation as long as all stored properties are Equatable/Hashable:
final class PlainClass: Hashable { let id: Int let name: String init(id: Int, name: String) { self.id = id self.name = name } // The compiler automatically synthesizes these methods—you don't need to write them! static func == (lhs: PlainClass, rhs: PlainClass) -> Bool { ... } func hash(into hasher: inout Hasher) { ... } }
二、第三方库增强(for advanced customization)
If you need more control—like automatically generating a toString()-style description (via CustomStringConvertible), handling non-conforming properties, or adding other protocol implementations—third-party code generation tools are a great fit.
Sourcery
Sourcery is a popular Swift code generator that uses templates to auto-generate protocol implementations. You just mark your types with special comments, and it generates extensions that stay in sync as you modify your type.
Example usage:
- Add a comment marker to your struct:
// sourcery: AutoHashable, AutoEquatable, AutoDescription struct EnhancedStruct { let id: Int let name: String let details: [String] }
- Sourcery will automatically generate this extension (and more):
extension EnhancedStruct: Hashable { static func == (lhs: EnhancedStruct, rhs: EnhancedStruct) -> Bool { lhs.id == rhs.id && lhs.name == rhs.name && lhs.details == rhs.details } func hash(into hasher: inout Hasher) { hasher.combine(id) hasher.combine(name) hasher.combine(details) } } extension EnhancedStruct: CustomStringConvertible { var description: String { return "EnhancedStruct(id: \(id), name: \(name), details: \(details))" } }
When you add a new field to EnhancedStruct, re-running Sourcery will update all generated code automatically.
三、How this compares to Java's AutoValue
- Built-in synthesis: Matches AutoValue's core benefit of "set it and forget it"—no tools, no extra code, just protocol conformance, and automatic updates when fields change.
- Third-party libraries: Offer more flexibility, like auto-generating human-readable string representations (similar to AutoValue's
toString()) or handling edge cases the compiler can't.
内容的提问来源于stack exchange,提问作者rinde

