So, while playing around with Swift, I ran into this issue and it's boggling my mind.
I have a class Card:
class Card {
var contents = ""
var chosen = false
var matched = false
var description: String {
get {
return self.contents
}
}
func match(otherCards: Card[]) -> Int {...}
}
and a class PlayingCard that subclasses Card:
class PlayingCard: Card {
var suit: Suit
var rank: Rank
override var contents: String {
get {
return "\(rank.description())\(suit.toRaw())"
}
set { }
}
init(rank: Rank, suit: Suit) {
self.suit = suit
self.rank = rank
super.init()
}
override func match(otherCards: Card[]) -> Int {...}
}
As you can see, in Card, the description
property is computed from the contents
property. However, when I instantiate a PlayingCard, I have a computed contents
property that overrides the stored contents
property of Card. However, if I call my PlayingCard's description
, it returns the Card's stored contents
, not PlayingCard's computed, actual contents
.
func testPlayingCardProperties() {
var card = PlayingCard(rank: .Ace, suit: .Spades)
XCTAssert(card.contents == "A♠️", "Contents not overriden.") // TRUE
XCTAssert(card.description == "A♠️", "Description not overriden.") // FALSE??
}
What's going on? Note that
func testCardProperties() {
var card = Card()
card.contents = "Test Card"
XCTAssert(card.contents == "Test Card", "Contents getter error.") // TRUE
XCTAssert(card.description == "Test Card", "Description getter error.") // TRUE
}
works as expected.
UPDATE
I ran the following in Playground... and it worked. Still no luck outside of it.
class Card {
var contents = ""
var chosen = false
var matched = false
var description: String {
get {
return contents
}
}
func match(otherCards: Card[]) -> Int {
var score = 0
for card in otherCards {
if card.contents == contents {
score += 1
}
}
return score
}
}
enum Suit: String {
case Diamonds = "♦️"
case Hearts = "♥️"
case Spades = "♠️"
case Clubs = "♣️"
static func allSuits() -> Suit[] {
return [.Diamonds, .Hearts, .Spades, .Clubs]
}
}
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func description() -> String {
switch self {
case .Ace:
return "A"
case .Jack:
return "J"
case .Queen:
return "Q"
case .King:
return "K"
default:
return String(toRaw())
}
}
}
class PlayingCard: Card {
var suit: Suit
var rank: Rank
override var contents: String {
get {
return "\(rank.description())\(suit.toRaw())"
}
set { }
}
let maxRank = 13
init(rank: Rank, suit: Suit) {
self.suit = suit
self.rank = rank
}
override func match(otherCards: Card[]) -> Int {
let allCards = otherCards + [self]
let testMatches = {
() -> (Card, Card[])[] in
var result: (Card, Card[])[] = []
for i in 0..allCards.count {
result += (allCards[i], Array(allCards[0..i] + allCards[(i + 1)..allCards.count]))
}
return result
}()
let scores = testMatches.map({
(card, otherCards) -> Int in
if let playingCard = card as? PlayingCard {
var rankValue = 1.0
var suitValue = 1.0
for matchCard in otherCards {
if let matchPlayingCard = matchCard as? PlayingCard {
if (matchPlayingCard.rank == playingCard.rank) {
rankValue *= 8;
} else {
rankValue /= 2;
}
if (matchPlayingCard.suit == playingCard.suit) {
suitValue *= 2;
} else {
suitValue /= 2;
}
}
}
if rankValue >= 1.0 {
return Int(rankValue)
} else if suitValue >= 1.0 {
return Int(suitValue)
} else {
return 0
}
} else {
return 0
}
})
return scores.reduce(Int.min, combine: { $0 > $1 ? $0 : $1 });
}
}
var card = PlayingCard(rank: .Jack, suit: .Spades)
card.description
Could this just be an Xcode bug?
There seems to be something odd, and likely buggy, going on. If I take this code:
class Base {
var contents = "Base contents"
var description: String {
get {
return self.contents
}
}
}
class Derived : Base {
override var contents: String {
get {
return "Derived contents, dynamically generated"
}
set { }
}
}
let d = Derived()
println(d.contents)
println(d.description)
...and put it in a single file (in a playground or on in a command-line OS X app), then the output is as follows (and I think, as expected):
println(d.contents) // Prints "Derived contents, dynamically generated"
println(d.description) // Prints "Derived contents, dynamically generated"
However, if I move out the Base class into "base.swift" and the Derived class into "derived.swift", leaving the main code in its own file, making no other changes, then it prints out:
println(d.contents) // Prints "Derived contents, dynamically generated"
println(d.description) // Prints "Base contents"
...which feels like a bug to me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With