没有泛型约束的协议中的泛型数组
Generic array in protocol without generic constraint
如何在符合类型指定数组类型的协议中指定泛型属性?
Info: Lets say we want to create a protocol which defines an array
property where the type of the array is unknown. The conforming types
specify the type of this array. This is a possible solution:
protocol Wallet {
associatedtype Value
var moneyStack: [Value] {get set}
}
struct BitcoinWallet: Wallet {
var moneyStack: [String]
}
struct EthereumWallet: Wallet {
var moneyStack: [Int]
}
The problem with this approach is that we can't access the moneyStack
property:
let bitcoinWallet = BitcoinWallet(moneyStack: ["A","B"])
let etheureumWallet = EthereumWallet(moneyStack: [1,2])
let wallets: [Wallet] = [bitcoinWallet, etheureumWallet]
for wallet in wallets {
print(wallet.moneyStack) // not possible
}
We can try another approach where the type of the array is any:
protocol Wallet {
var moneyStack: [Any] {get set}
}
struct BitcoinWallet: Wallet {
var moneyStack: [Any]
}
struct EthereumWallet: Wallet {
var moneyStack: [Any]
}
This is a possible solution but an array which holds [Any] is too
generic. I can't specify the type. Example:
let bitcoinWallet = BitcoinWallet(moneyStack: ["A","B"])
let ethereumWallet = EthereumWallet(moneyStack: [1,2])
var wallets: [Wallet] = [bitcoinWallet, ethereumWallet]
for wallet in wallets {
print(wallet.moneyStack.count) // this works
print(wallet.moneyStack[0]) // this works
}
let badBitcoinWallet = BitcoinWallet(moneyStack: [12.4, 312312.123]) // BitcoinWallets aren't allowed to hold doubles!
wallets.append(badBitcoinWallet) // This shouldn't be allowed!
第一个方案就是我想要的。每个结构中都指定了类型,但 Swift 抱怨我不能使用通用约束。我要解决的主要问题是我想要一个包含不同类型钱包的数组,它们都有自己不同类型的数组。
我原以为协议会让这件事变得简单,但事实并非如此。我的架构有问题吗?我什至应该使用协议吗?也许子类化可以解决这个问题?
您不能在数组中存储 2 个不同类型的对象(Wallet<String>
和 Wallet<Int>
是不同的类型)。
但你可以尝试这样的事情:
protocol WalletProtocol {
func printMoneyStack()
}
class Wallet<T> {
var moneyStack: [T] = []
init(moneyStack: [T]) {
self.moneyStack = moneyStack
}
}
class BitcoinWallet: Wallet<String>, WalletProtocol {
func printMoneyStack() {
print(moneyStack)
}
}
class EthereumWallet: Wallet<Int>, WalletProtocol {
func printMoneyStack() {
print(moneyStack)
}
}
let bitcoinWallet = BitcoinWallet(moneyStack: ["A","B"])
let etheureumWallet = EthereumWallet(moneyStack: [1,2])
let wallets: [WalletProtocol] = [bitcoinWallet, etheureumWallet]
for wallet in wallets {
wallet.printMoneyStack()
}
如何在符合类型指定数组类型的协议中指定泛型属性?
Info: Lets say we want to create a protocol which defines an array property where the type of the array is unknown. The conforming types specify the type of this array. This is a possible solution:
protocol Wallet {
associatedtype Value
var moneyStack: [Value] {get set}
}
struct BitcoinWallet: Wallet {
var moneyStack: [String]
}
struct EthereumWallet: Wallet {
var moneyStack: [Int]
}
The problem with this approach is that we can't access the moneyStack property:
let bitcoinWallet = BitcoinWallet(moneyStack: ["A","B"])
let etheureumWallet = EthereumWallet(moneyStack: [1,2])
let wallets: [Wallet] = [bitcoinWallet, etheureumWallet]
for wallet in wallets {
print(wallet.moneyStack) // not possible
}
We can try another approach where the type of the array is any:
protocol Wallet {
var moneyStack: [Any] {get set}
}
struct BitcoinWallet: Wallet {
var moneyStack: [Any]
}
struct EthereumWallet: Wallet {
var moneyStack: [Any]
}
This is a possible solution but an array which holds [Any] is too generic. I can't specify the type. Example:
let bitcoinWallet = BitcoinWallet(moneyStack: ["A","B"])
let ethereumWallet = EthereumWallet(moneyStack: [1,2])
var wallets: [Wallet] = [bitcoinWallet, ethereumWallet]
for wallet in wallets {
print(wallet.moneyStack.count) // this works
print(wallet.moneyStack[0]) // this works
}
let badBitcoinWallet = BitcoinWallet(moneyStack: [12.4, 312312.123]) // BitcoinWallets aren't allowed to hold doubles!
wallets.append(badBitcoinWallet) // This shouldn't be allowed!
第一个方案就是我想要的。每个结构中都指定了类型,但 Swift 抱怨我不能使用通用约束。我要解决的主要问题是我想要一个包含不同类型钱包的数组,它们都有自己不同类型的数组。
我原以为协议会让这件事变得简单,但事实并非如此。我的架构有问题吗?我什至应该使用协议吗?也许子类化可以解决这个问题?
您不能在数组中存储 2 个不同类型的对象(Wallet<String>
和 Wallet<Int>
是不同的类型)。
但你可以尝试这样的事情:
protocol WalletProtocol {
func printMoneyStack()
}
class Wallet<T> {
var moneyStack: [T] = []
init(moneyStack: [T]) {
self.moneyStack = moneyStack
}
}
class BitcoinWallet: Wallet<String>, WalletProtocol {
func printMoneyStack() {
print(moneyStack)
}
}
class EthereumWallet: Wallet<Int>, WalletProtocol {
func printMoneyStack() {
print(moneyStack)
}
}
let bitcoinWallet = BitcoinWallet(moneyStack: ["A","B"])
let etheureumWallet = EthereumWallet(moneyStack: [1,2])
let wallets: [WalletProtocol] = [bitcoinWallet, etheureumWallet]
for wallet in wallets {
wallet.printMoneyStack()
}