【问题标题】:How can I change the property value in subclass within swift?如何在 swift 中更改子类中的属性值?
【发布时间】:2023-04-08 19:10:01
【问题描述】:

根据 swift 语言指南的继承章节,我尝试在子类中编写计算人员。当我将 newValue 设置为类实例的属性时,setter 似乎工作,而属性值没有转换为 newValue。

class Vehicle {
    var currentSpeed = 1.0
    var description: String {
        return "The current speed is \(currentSpeed) miles per hour"
    }
    func makeNoise() {
    }
}
class Car: Vehicle {
    var gear = 0
    override var description: String {
        return super.description + " in gear \(gear)"
    }
}
class AutomaticCar: Car {
    override var currentSpeed: Double {
        get {
            return super.currentSpeed
        }
        set {
            gear = Int(newValue/10) + 1
        }
    }
}

let automaticCar = AutomaticCar()
automaticCar.currentSpeed = 12.0
print(automaticCar.currentSpeed)//It prints "1.0"
print(automaticCar.description)//It prints "The current speed is 1.0 miles per hour in gear 2"

automaticCar.currentSpeed 的属性值仍然是“1.0”而不是“12.0”,而实例的 gear 属性似乎生效了。查了也没找到答案,是什么原理导致出现这种情况的?

另一个问题:

class A {
    var test1 = 1
    var test2 = 2
    var sum: Int {
        get {
            return test1 + test2
        }
        set {
            test1 = newValue - test2
        }
    }
}
var a = A()
print(a.sum)
a.sum = 4
print(a.sum)//It ptints "4"
print(a.test1)//It prints "2"

在这种情况下,我不需要刻意设置新的sum属性的值,这两种情况有什么区别?

【问题讨论】:

    标签: swift inheritance subclass getter-setter


    【解决方案1】:
    class AutomaticCar: Car {
        override var currentSpeed: Double {
            get {
                return super.currentSpeed
            }
            set {
                super.currentSpeed = newValue
                gear = Int(newValue/10) + 1
            }
        }
    }
    

    您刚刚忘记在覆盖的 setter 中设置 currentSpeed 的值。

    【讨论】:

    • 或者,您可以覆盖 didSet 属性观察者 - override var currentSpeed: Double { didSet { gear = Int(currentSpeed / 10) + 1 } }
    • 感谢您的帮助。我想知道在另一种情况下,为什么我不需要在我的 setter 中设置 a.sum 的值?类和子类有什么区别吗?
    • @astost 你自己搞糊涂了。它与类与子类无关。它与存储属性与计算属性有关。 — 正如 Hamish 所说的那样,如果您的 currentSpeed 覆盖是 setter 观察者而不是计算属性,这将更加简单和清晰。
    • @matt 第一种情况的 automaticCar.currentSpeed 和第二种情况的 a.sum 都是计算属性,但是需要在 setter 中设置 currentSpeed 的值,而似乎不需要设置setter 中 sum 的值。我对这两种情况在方面的区别感到困惑。
    • @astost 您在“不需要”这句话上模棱两可。没有必要,因为在您的 class A 示例中,计算属性取决于您在 setter 中操作的两个存储属性。然后吸气剂会给出“正确”的答案。好吧,AutomaticCar 也是如此——它依赖于一个存储的属性,如果你想在 its getter 中获得“正确”的答案,你必须操纵它。换句话说,在 A 类中,你的 getter 和你的 setter 一起去,但在你的 AutomaticCar 中,你的 getter 和你的 setter一起去。
    【解决方案2】:

    在你的真实例子中:

    • Vehicle currentSpeed 是一个存储的属性。这意味着您可以直接分配给它,并且属性值会发生变化。

    • AutomaticCar currentSpeed 实际上是一个不同 属性——一个计算 属性。这意味着当您分配给它时,所发生的只是set 函数运行。存储的属性值不会因此而改变,除非set 函数中更改它们。

    好吧,在 AutomaticCar 的 currentSpeed set 函数中,您没有将新值存储在存储属性 Vehicle 的 currentSpeed 中。因此它没有改变,因为没有任何事情会改变它。

    正如 Hamish 在评论中所说的那样,您的意思可能是这样的:

    class AutomaticCar: Car {
        override var currentSpeed: Double {
            didSet {
                self.gear = Int(self.currentSpeed/10) + 1
            }
        }
    }
    

    在该公式中,AutomaticCar currentSpeed 不是计算属性;它 Vehicle currentSpeed — 它是同一个存储属性,还有一个 setter 观察者。因此,设置它会设置它,存储新值 — 再加上现在我们运行 setter 观察器并在 self.gear 中进行您所追求的更改。

    请注意,子类中存储属性的覆盖必须是一个或另一个,要么是独立的计算属性,要么是添加了 setter 观察器的原始存储属性。它本身不能是一个独立的存储属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-20
      • 2020-11-10
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 2017-09-07
      • 1970-01-01
      相关资源
      最近更新 更多