簡體   English   中英

Swift 3泛型函數模棱兩可的回報

[英]Swift 3 generic function ambiguous return

我需要一個函數來解決類中的不同依賴關系。 但是出現了編譯錯誤。 是否可以創建該泛型函數,或者Swift中存在一些編譯器約束?

import Foundation

protocol Client: class {
    var description: String { get }
}
final class ImportantPerson : Client {
    var description: String {
        return "Important person"
    }
}

protocol Order: class {
    var description: String { get }
}
final class LastOrder : Order {
    var description: String {
        return "Last order"
    }
}

final class A {

    fileprivate func resolveDependency<T>() -> T {
        return resolve() as T
    }

    private func resolve() -> Client {
        return ImportantPerson()
    }
    private func resolve() -> Order {
        return LastOrder()
    }

}

let a = A()
let client: Client = a.resolveDependency()
let order: Order = a.resolveDependency()

print("Client: \(client.description)")
print("Order: \(order.description)")

編輯 :這個問題與Swift是否允許創建兩個僅返回類型不同的函數無關。 我知道有可能 我認為編譯器中存在一些人為的約束,但基本邏輯中沒有,應允許從上下文中推斷所需的類型。

讓我們投入到編譯器的工作中。 想象一下,這沒有引起錯誤,並且您有一個簽名和不同的輸出。

每當您調用resolveDependency<T>() -> T ,編譯器都會為您返回類型T ,該類型T是符合您所用協議的實例。

在您的代碼中,使用符合同一協議的不同實例調用此方法。 在那個階段,編譯器對此還一無所知。 它只知道你已經通過實例T ,它需要給你的形狀結果T

到現在為止沒有問題。 一旦執行

return resolve() as! T

編譯器會感到困惑。 我有一個T但是我不知道我將調用哪個resolve() ...我所知道的就是我有一個T 我怎么知道這是Order還是Client

為了避免此類混淆,我們存在編譯時錯誤。 至少Swift就是這種情況。 (我不知道其他語言的工作原理)

您需要使用不同的簽名定義不同的方法,並相應地轉換類型以獲得相似的結果

fileprivate func resolveDependency<T>() -> T {
  // check if this is an Order
  resolveForOrder()

  // check if this is a Client
  resolveForClient()
}

private func resolveForOrder() -> Order {
  return LastOrder()
}

private func resolveForClient() -> Client {
  return ImportantPerson()
}

這就像試圖用汽車修理工修理航天飛機發動機一樣。 是的,他們倆都有發動機,都以燃料為動力,但是機械師只知道如何修理汽車發動機,因為他不是火箭科學家(!)

這段代碼可以正常工作:

import Foundation

protocol Client: class {
    var description: String { get }
}
final class ImportantPerson : Client {
    var description: String {
        return "Important person"
    }
}

protocol Order: class {
    var description: String { get }
}
final class LastOrder : Order {
    var description: String {
        return "Last order"
    }
}

final class A {

    fileprivate func resolveDependency<T>() -> T {
        if T.self == Client.self {
            return resolve() as Client as! T
        } else {
            return resolve() as Order as! T
        }
    }

    private func resolve() -> Client {
        return ImportantPerson()
    }
    private func resolve() -> Order {
        return LastOrder()
    }

}

let a = A()
let client: Client = a.resolveDependency()
let order: Order = a.resolveDependency()

print("Client: \(client.description)")
print("Order: \(order.description)")

但是我相信編譯器應該自己解決if else子句,這並不像我想的那么難。 另外,當編譯器嘗試匹配以下類型時,還會出現一些錯誤:

    switch T.self {
    case is Client:
        return resolve() as Client as! T
    default:
        return resolve() as Order as! T
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM