(使用我常用的扑克牌示例)
我正在尝试制作一个通用的 CardCollection
两者都是Deck
和一个 Hand
将继承自。牌组和手牌都需要排序或洗牌,但会有一些差异,例如初始化以及是否删除 Card
的方法。在其他地方使用的是 Deal
(对于 Deck
), Play
,或Discard
(对于 Hand
s)。
class CardCollection: <Some protocol or another that Arrays use> {
var collective = [Card]()
// CardCollection-specific functions
// pass-through functions
func append(newCard: Card) {
collective.append(newCard)
}
}
class Deck: CardCollection {
// deck-specific functions
}
class Hand: CardCollection {
// hand-specific functions
}
我目前实现它的方式(见上文)是使用一个包含卡片数组的类,但是如果不编写大量的传递函数来获取我的类,我就无法像数组一样使用我的类以数组形式遵守所有协议(protocol)。
我需要的是一种让我可以做类似 for card in deck
之类的事情的方法(就好像 deck
只是一个 Array<Card>
),而无需编写大量包装函数来获取 CardCollection
遵守所有必要的协议(protocol)。
如何制作一个功能就像 Array<Card>
的 CardCollection无需对 Array
协议(protocol)使用的每个函数都创建传递函数用途?
最佳答案
您可以定义一个 CardCollection
协议(protocol),该协议(protocol)继承自
RangeReplaceableCollectionType
,
以及具有默认实现的协议(protocol)扩展以转发所有
访问底层collective
数组的方法:
struct Card {
// Simplified for demonstration purposes:
let rank : Int
let suit : Int
}
protocol CardCollection : RangeReplaceableCollectionType {
var collective : [Card] { get set }
}
extension CardCollection {
var startIndex : Int { return collective.startIndex }
var endIndex : Int { return collective.endIndex }
subscript(position : Int) -> Card {
get {
return collective[position]
}
set(newElement) {
collective[position] = newElement
}
}
mutating func replaceRange<C : CollectionType where C.Generator.Element == Card>(subRange: Range<Int>, with newElements: C) {
collective.replaceRange(subRange, with: newElements)
}
}
然后
struct Deck: CardCollection {
var collective = [Card]()
}
struct Hand: CardCollection {
var collective = [Card]()
}
两者都符合RangeReplaceableCollectionType
并且可以被处理
就像一个数组:
var deck = Deck()
deck.append(Card(rank: 1, suit: 1))
deck[0] = Card(rank: 2, suit: 3)
for card in deck {
print(card)
}
var hand = Hand()
hand.append(deck.first!)
如果Deck
/Hand
是类而不是结构,那么它们
需要是final
或者有一个必需的init()
方法,
比较
Why use required Initializers in Swift classes? .
更一般一点,您可以定义一个ElementCollection
协议(protocol)(独立于卡
类型)
其行为类似于数组(通过符合
RangeReplaceableCollectionType
)并将访问权限转发到
底层 elements
数组:
protocol ElementCollection : RangeReplaceableCollectionType {
typealias Element
var elements : [Element] { get set }
}
extension ElementCollection {
var startIndex : Int { return elements.startIndex }
var endIndex : Int { return elements.endIndex }
subscript(position : Int) -> Element {
get {
return elements[position]
}
set(newElement) {
elements[position] = newElement
}
}
mutating func replaceRange<C : CollectionType where C.Generator.Element == Element>(subRange: Range<Int>, with newElements: C) {
elements.replaceRange(subRange, with: newElements)
}
}
然后用作
struct Card {
// Simplified for demonstration purposes:
let rank : Int
let suit : Int
}
struct Deck: ElementCollection {
var elements = [Card]()
}
struct Hand: ElementCollection {
var elements = [Card]()
}
关于arrays - 如何扩展特定类型数组的数组功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34237047/