用 Swift 5 动态值初始化属性包装器

5

情境:

  1. 我想要不同类型的债券,这些债券具有最低价值、弹性利息现值(根据某些逻辑计算)和债券增长预测。

  2. 每当债券价值超过最低价值时,增长预测变得升值,反之亦然。

  3. 我可以拥有多个具有自己价值集合的债券。

我尝试使用属性包装器来实现相同的功能,以便我不必为每种债券复制相同的行为:

 @propertyWrapper
struct BondValue {
    private var bondCurrentWorth: Int
    private var minimumValue: Int
    private var flexiInterest: Int
    
    var projectedValue: BondGrowth = .appreciating // The projected value projects the growth for the bond
    
    var wrappedValue: Int {

        get {
            return bondCurrentWorth
        }
        
        set {
            bondCurrentWorth = newValue + (newValue * flexiInterest/100)
            projectedValue = bondCurrentWorth < minimumValue ? .depriciating : .appreciating
        } 
 }
    
    init(wrappedValue: Int = 0, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.minimumValue = minimumValue
        self.flexiInterest = flexiInterest
        self.bondCurrentWorth = value
    }
}

现在,对于创建任何债券,我做如下操作:

struct FoodBond {
    var bondName: String
    @BondValue(minimumValue: 200, flexiInterest: 30, value: 200) var value = 30
    
    init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.bondName = bondName
    }
}

问题陈述:

  • 我无法使用动态值来初始化bondvalue。

可能的解决方法: 在下面的实现中,我将使用与普通结构体相同的方法。虽然文档中也指定了使用属性包装器的方式,但是这种方法会使语法变得复杂。

您可以编写代码以利用属性包装器的行为, 而不必使用特殊的属性语法。例如, 这里是从前面的代码清单中包装其属性的SmallRectangle版本 在其中,显式地将其属性包装在TwelveOrLess结构中,而不是将@TwelveOrLess编写为属性。

@propertyWrapper
struct BondValue {
    private (set) var bondCurrentWorth: Int
    private (set) var minimumValue: Int
    private (set) var flexiInterest: Int
    
    var projectedValue: BondGrowth = .appreciating // The projected value projects the growth for the bond
    
    var wrappedValue: Int { .... }
    
    init(wrappedValue: Int = 0, minimumValue: Int, flexiInterest: Int, value: Int) { ... }
}

struct FoodBond {
    var bondName: String
    var value = BondValue(minimumValue: 0, flexiInterest: 0, value: 0) // Provide a default value
    
    init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.bondName = bondName
        self.value = BondValue(minimumValue: minimumValue, flexiInterest: flexiInterest, value: value)
    }
}

var foodBond = FoodBond(bondName: "Food Bond", minimumValue: 200, flexiInterest: 10, value: 200)
print("Initial bond current worth - \(foodBond.value.bondCurrentWorth)")
print("Bond growth - \(foodBond.value.projectedValue)")

任何建议都将非常有帮助。

2个回答

5
关于Swift提案文档中有关属性包装器的部分成员初始化器

具有属性包装器的实例属性将在成员初始化器中具有相应的参数,其类型将取决于包装器类型和初始值(如果提供),可能是原始属性类型或包装器类型之一。

解决方案:

struct FoodBond {
    var bondName: String

    @BondValue(minimumValue: 0, flexiInterest: 0, value: 0) var bondValue = 0

    init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.bondName = bondName
        _bondValue = BondValue(minimumValue: minimumValue, flexiInterest: flexiInterest, value: value)
    }
}

1
您可以使用不带参数的属性包装器,并将其类型设置为包装值的类型,然后在init中使用您的参数创建它:
struct FoodBond {
    var bondName: String

    @BondValue var bondValue : Int

    init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.bondName = bondName
        _bondValue = BondValue(minimumValue: minimumValue, flexiInterest: flexiInterest, value: value)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接