代码之家  ›  专栏  ›  技术社区  ›  Joris

Swift泛型,数组与单个对象的函数名可能相同吗?

  •  0
  • Joris  · 技术社区  · 3 年前

    是否可以编写一个返回类型的泛型函数 T 一个同名返回 [T] ?

    例子:

        static func processResult<T: Decodable>(_ inputData: Data) -> [T] { ... }
        static func processResult<T: Decodable>(_ inputData: Data) -> T { ... }
    

    所以打电话时,我可以:

        let myObj: Car = processResult(data)
        ...
    
        let myObjs: [Car] = processResult(data)
    
    

    我推测从技术上讲 T 也可以被视为 T 类型,因此编译器会感到困惑。没办法这么说 T 不会是数组类型吗?

    1 回复  |  直到 3 年前
        1
  •  1
  •   CouchDeveloper    3 年前

    当你有机会在函数定义中设置约束时,你也可以这样做:

    func processResult<T: Decodable & Collection>(_ inputData: Data) -> T { ... }
    func processResult<T: Decodable>(_ inputData: Data) -> T { ... }
    

    编译器将始终选择“最专业”的候选者。因此,如果您的结果类型符合 Collection ,总是第一个被选中的候选人。

    否则,如果找到其他候选人。

        2
  •  0
  •   Sweeper    3 年前

    没有办法说t不是数组类型吗?

    好吧,如果你能找到一个协议 P 向哪个 Array 不符合,但其他所有 T 您想使用第二个重载 符合,然后您可以执行:

    func processResult<T: Decodable>(_ inputData: Data) -> [T] {
        ...
    }
    func processResult<T: Decodable & P>(_ inputData: Data) -> T {
        ...
    }
    
    struct SomeStruct : Decodable, P { ... }
    
    let x: SomeStruct = processResult(someData) // second overload
    let y: [SomeStruct] = processResult(someData) // first overload
    

    是否可以编写一个返回类型的泛型函数 T 一个同名返回 [T] ?

    当然,您只需要显式传递类型参数,以帮助编译器推断出 T 是:

    func processResult<T: Decodable>(_ inputData: Data, _ type: T.Type) -> [T] {
        ...
    }
    func processResult<T: Decodable>(_ inputData: Data, _ type: T.Type) -> T {
        ...
    }
    
    struct SomeStruct : Decodable { ... }
    
    let x: SomeStruct = processResult(someData, SomeStruct.self) // second overload
    let y: [SomeStruct] = processResult(someData, SomeStruct.self) // first overload
    

    你可能会认为这句话 SomeStruct 两次是冗长的,但在这里是非常必要的——没有第一次 有些真实 ,您要调用哪个重载是不明确的,因为这两个重载仅在返回类型上不同。没有第二个 有些真实 ,什么是模棱两可的 T 正如你所说, T 也可以是数组。

        3
  •  0
  •   Daveloper    3 年前

    是的,这是可能的,但你不需要返回[t],你只能返回t,但你必须将其转换为[Car]

    func processResult<T: Decodable>(_ inputData: Data) -> T {
       return try! JSONDecoder().decode(T.self, from: inputData)
    }
    
    struct Car: Decodable {
    
    }
    
    let cars: [Car] = processResult(Data())
    let car: Car = processResult(Data())
    
        4
  •  0
  •   Mojtaba Hosseini    3 年前

    正如你在 Swift Language Source Code ,

    extension Array: Decodable where Element: Decodable { ... }
    

    Array 将是一个 Decodable 如果它的所有元素都是 可解码 因此,如果你尝试使用泛型,编译器只会将你传递给函数的协议视为 T 这就是 可解码 在你的情况下。

    所以 T 将被视为 some Decodable

    也, [T] 将被视为 一些可解码

    要解决此问题,请执行以下操作:

    你可以屏蔽 Swift.Decodable :

    protocol Decodable: Swift.Decodable {}
    

    因此,您的代码应该可以在不需要任何其他更改的情况下工作。


    p.s:我认为Swift应该从赋值运算符的左侧或类型转换的右侧自动推断它!但我知道Swift开发人员正在努力实现这些事情,即使是类型推理的一个重大增强,也会在这么多年后推出Swift 5.4!