(使用我常用的扑克牌示例)
我正在尝试制作CardCollection
和Deck
都可以继承的通用Hand
。 Decks和Hands都需要进行排序或改组,但是会有一些差异,例如初始化以及删除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
}
我目前正在实现它的方式(见上文)是一个包含一个数组卡的类,但我不能使用我的类,就像它们是数组而没有编写大量的传递函数来获取我的类将所有协议都作为数组使用。
我需要的是一种允许我执行for card in deck
之类的方式(好像deck
只是Array<Card>
),而不需要编写大量的包装函数来获取{ {1}}以符合所有必要的协议。
如何在CardCollection
使用的协议所使用的每个函数上创建一个只有Array<Card>
的函数的CardCollection?
答案 0 :(得分:4)
您可以定义继承自的CardCollection
协议
RangeReplaceableCollectionType
,
和一个协议扩展,默认实现转发所有
访问基础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
或required init()
方法,
相比
Why use required Initializers in Swift classes?
稍微更一般的是,您可以定义ElementCollection
协议(独立于Card
类型)
其行为类似于数组(通过符合
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]()
}