swift 如何在init函数中调用结构体中的函数?

m1m5dgzv  于 2023-01-25  发布在  Swift
关注(0)|答案(4)|浏览(139)

我希望在一个结构体中有一个可重用的函数,我可以在我的init方法中调用它。然而,当我这样做时,我得到了下面的错误。
在初始化所有存储的属性之前使用了“self”
如何在init方法中使用calculateValue而不引发此错误?我将在结构体的其他部分使用calculateValue函数,因此我不希望它存在于init函数中。

struct Card {
    let face: Face
    let suit: Suit
    let value: Int

    init(face: Face, suit: Suit) {
        self.face = face
        self.suit = suit
        self.value = self.calculateValue(face: face)
    }

    private func calculateValue(face: Face) -> Int {
        if face == Face.two { return 2 }
        if face == Face.three { return 3 }
        if face == Face.four { return 4 }
        if face == Face.five { return 5 }
        if face == Face.six { return 6 }
        if face == Face.seven { return 7 }
        if face == Face.eight { return 8 }
        if face == Face.nine { return 9 }
        return 10
    }
}
blpfk2vs

blpfk2vs1#

我能想到两个可能的解决办法。
1.使calculateValue成为静态函数,因为它不依赖于任何状态。

struct Card {
    let face: Face
    let suit: Suit
    let value: Int

    init(face: Face, suit: Suit) {
        self.face = face
        self.suit = suit
        self.value = Card.calculateValue(face: face)
    }

    private static func calculateValue(face: Face) -> Int {
        if face == Face.two { return 2 }
        if face == Face.three { return 3 }
        if face == Face.four { return 4 }
        if face == Face.five { return 5 }
        if face == Face.six { return 6 }
        if face == Face.seven { return 7 }
        if face == Face.eight { return 8 }
        if face == Face.nine { return 9 }
        return 10
    }
}

1.将返回值的功能移到Face枚举中。下面是使用计算的value属性对Face枚举进行的部分猜测:

enum Face {
    case two
    case three
    case jack

    var value: Int {
        switch self {
        case .two:
            return 2
        case .three:
            return 3
        default:
            return 10
        }
    }
}

那么Card就变成了:

struct Card {
    let face: Face
    let suit: Suit
    let value: Int

    init(face: Face, suit: Suit) {
        self.face = face
        self.suit = suit
        self.value = face.value
    }
}

尽管现在您甚至不需要value属性,或者您可以将其设置为计算属性。

55ooxyrt

55ooxyrt2#

我的建议是用Int原始值声明枚举,只要分配初始原始值就足够了,编译器就会推断出序列

enum Face : Int {
    case two = 2, three, four, five, six, seven, eight, nine, ten, jack, queen, king, ace
}

Card中,用computed属性得到一个值,如果小于10,则返回face的原始值,否则为10。

struct Card {
    let face: Face
    let suit: Suit
    
    var value: Int { 
       return face.rawValue < 10 ? face.rawValue : 10
    }
}

init方法是免费的。

dwbf0jvd

dwbf0jvd3#

把它移到Face本身怎么样,例如..

enum Face {
    case two, three, four, five, six, seven, eight, nine, ten, jack, queen, king

    var value: Int {
        switch self {
        case .two: return 2
        case .three: return 3
        case .four: return 4
        case .five: return 5
        case .six: return 6
        case .seven: return 7
        case .eight: return 8
        case .nine: return 9
        default: return 10
        }
    }
}

那么你的姓名首字母可以是...

struct Card {
    let face: Face
    let suit: Suit
    let value: Int
    
    init(face: Face, suit: Suit) {
        self.face = face
        self.suit = suit
        self.value = face.value
    }    
}
fumotvh3

fumotvh34#

让我再提一个建议:只需让Face值具有Int原始值:

enum Face: Int {
    case ace   = 1
    case two   = 2
    case three = 3
    case four  = 4
    case five  = 5
    case six   = 6
    case seven = 7
    case eight = 8
    case nine  = 9
    case ten   = 10
    case jack  = 11
    case queen = 12
    case king  = 13
}

这时,你可以只设置self.value = face.rawValue,但是你不应该这样做,因为你会有一个分离的真值源,Card结构体不需要值的副本,它们只需要访问面的值,它们已经包含了:

struct Card {
    let face: Face
    let suit: Suit
    
    init(face: Face, suit: Suit) {
        self.face = face
        self.suit = suit
    }
    
    var value: Int { self.face.rawValue }
}

相关问题