簡體   English   中英

在Swift中將抽象類型轉換為具體類型

[英]Convert Abstract Type to Concrete Type in Swift

我正在嘗試為我的應用制作數據模型。 這是場景:

我的應用程序具有“客戶模型”,其中包含客戶的信息,還包含他/她的“付款來源”。 API為我提供了兩種付款方式: 銀行帳戶 ,它們具有完全不同的字段。

所以,這是我的問題,我想要一個抽象類型,即PaymentSource,然后在每個PaymentSource中都有一個函數,用於返回轉換為該類型的對象。 我如何進行類型擦除。

我需要將抽象類型放在一個盒子中,並將其用作具體類型(AnyPaymentSource)。

因此,我已完成以下操作:

protocol PaymentSource {
    associatedtype Kind
    func cast() -> Kind
}

struct AnyPaymentSource<PS: PaymentSource> {
    private var paymentSource: PS
    init(paymentSource: PS) {
        self.paymentSource = paymentSource
    }
    func cast() -> PS.Kind {
        return paymentSource.cast()
    }
}

struct Card: PaymentSource {
    func cast() -> Card {
        return self
    }
}

struct BankAccount: PaymentSource {
    func cast() -> BankAccount {
        return self
    }
}

struct Customer { 
    var firstName: String
    var lastName: String
    var email: String
    var paymentSource : AnyPaymentSource<PaymentSource> 
}

Customer通過以下說明給我錯誤:

不支持將“ PaymentSource”用作符合協議“ PaymentSource”的具體類型

我在哪里做錯了?

Swift是靜態類型的語言 這意味着必須在編譯時知道變量的類型。

當我遇到這個問題時,我解決了這樣的問題

protocol PaymentSource {
    associatedtype Kind
    func cast() -> Kind
}

struct AnyPaymentSource<PS: PaymentSource> {
    private var paymentSource: PS
    init(paymentSource: PS) {
        self.paymentSource = paymentSource
    }
    func cast() -> PS.Kind {
        return paymentSource.cast()
    }
}

struct Card: PaymentSource {
    func cast() -> Card {
        return self
    }
}

struct BankAccount: PaymentSource {
    func cast() -> BankAccount {
        return self
    }
}

struct Customer<T:PaymentSource> {
    var firstName: String
    var lastName: String
    var email: String
    var paymentSource : AnyPaymentSource<T>
}
func test(){
    let customerWithCard = Customer<Card>(
        firstName: "",
        lastName: "",
        email: "",
        paymentSource: AnyPaymentSource(paymentSource: Card())
    )
    let customerWithBankAccount = Customer<BankAccount>(
        firstName: "",
        lastName: "",
        email: "",
        paymentSource: AnyPaymentSource(paymentSource: BankAccount())
    )
    print(customerWithCard.paymentSource.cast())
    print(customerWithBankAccount.paymentSource.cast())
    return
}

如果您要實現的目標是@Andrew Ashurov在他的回答中提到的目標,則無需實現AnyPaymentSource Swift協議文檔中所述

協議本身實際上並未實現任何功能。 但是, 您創建的任何協議都將成為可 在您的代碼中使用 的完整類型

意味着已經能夠將協議視為類型

有可能:

protocol PaymentSource {
    func cast() -> Self
}

struct Card: PaymentSource {
    func cast() -> Card {
        return self
    }
}

struct BankAccount: PaymentSource {
    func cast() -> BankAccount {
        return self
    }
}

struct Customer {
    var firstName: String
    var lastName: String
    var email: String
    var paymentSource : PaymentSource?
}

創建客戶:

let cardCustomer = Customer(firstName: "Card Fname", lastName: "Card Lname", email: "cardemail@example.com", paymentSource: Card())

let bankAccountCustomer = Customer(firstName: "Bank Account Fname", lastName: "Bank Account Lname", email: "bankaccountemail@example.com", paymentSource: BankAccount())

請注意,在“ Customer結構中, PaymentSource類型的paymentSource屬性意味着可以將其分配為符合PaymentSource協議的任何類型(在您的情況下為CardBankAccount )。

暫無
暫無

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

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