声明一个专用于不同类型的泛型结构的数组



我知道 Swift 没有通配符类型来专门处理泛型类型。我有一个问题,我会知道如何在像Java这样的语言中使用它们来解决。

在下面的示例中,我尝试定义一个结构Property,该结构封装对类型属性的访问,T执行两个操作,在 T 实例上获取该属性值的哈希值,并在两个T实例上比较该属性的值。为了允许这一点,结构包含一个属性getter保存一个函数,该函数返回实例上特定属性的值。因此,结构不仅需要在T中是泛型的,而且在属性的类型E中也需要泛型。

在结构式Test中,我想定义一个静态属性properties保存一个Property实例的数组,每个属性对应一个Test。我看不到一种方法可以做到这一点,因为我不知道properties使用什么类型或如何"隐藏"类型参数E以便不需要在properties声明中指定它。

// Struct which represents a property of type T with a value of type E.
// Aside from initialization only T is visible from outside.
public struct Property<T, E: Hashable> {
let getter: (T) -> E
func getMemberHashValue(instance: T) -> Int {
return getter(instance).hashValue
}
func equalsMembers(instance1: T, instance2: T) -> Bool {
return getter(instance1) == getter(instance2)
}
}
struct Test {
// Some properties with different types
let a: Int
let b: Double
// Array of Property instances for all properties of Test.
// Not valid syntax.
let properties: [Property<Test, ?>] = [
Property(getter: { (instance: Test) in instance.a }),
Property(getter: { (instance: Test) in instance.b })]
}

我知道在这种情况下,我可以将 AnyHashable 替换为properties声明中的第二个类型参数,因为它没有关联的类型,但我想找到一个通用解决方案,我可以在不涉及Hashable的情况下应用。

有没有办法更改此示例以允许定义此类属性properties,其中包含不同类型的属性的多个Property实例?

概述:

  • 不确定我是否正确理解了你的问题。
  • 可能值得说明为什么你想要一个异构数组,在这个过程中会失去所有类型的安全性。
  • 可能正在重新审视设计

选项 1:

如果绝对需要,如果是这样,只需使用NSArray/NSMutableArray

选项 2:

如果要动态访问class/struct/enum的属性,可以使用KeyPath.

法典:

struct Test : Hashable {
// Some properties with different types
let a: Int
let b: Double
let c: String
//This function will return any property of Test instance
func property<T>(forKeyPath keyPath: KeyPath<Test, T>) -> T {
return self[keyPath: keyPath]
}
//MARK: Hashable
var hashValue: Int {
return a.hashValue ^ b.hashValue ^ c.hashValue
}
//MARK: Equatable
static func ==(lhs: Test, rhs: Test) -> Bool {
return lhs.a == rhs.a &&
lhs.b == rhs.b &&
lhs.c == rhs.c
}
}
let test1 = Test(a: 10, b: 22.22, c: "aaaa")
let cValue      = test1.property(forKeyPath: .c)           //aaaa
let cHashValue  = test1.property(forKeyPath: .c.hashValue) //Hash value of aaaa
let someInt = 10 //This is also Hashable
var mixedArray = [AnyHashable]()
mixedArray.append(test1)
mixedArray.append(someInt)

指:

如果这符合您的要求,请阅读有关KeyPathPartialKeyPath的信息。

版本:

斯威夫特 4

最新更新