如何用各种继承的参数覆盖一个函数(Swift)

问题描述 投票:0回答:2

如何在Swift中使用继承参数覆盖函数?

我有课:

class ItemA {
    var valueA: String?
    func setValueA(_ value: String?) {
        valueA = value
    }
}

class ItemB: ItemA {
    var valueB: String?
    func setValueB(_ value: String?) {
        valueB = value
    }
}

// Analog of the abstract class
class ClassA {
    func setValues(_ item: ItemA) {
        item.setValueA("valueA")
        getValues(item) // call getValues from ClassB
    }
    func getValues(_ item: ItemA) {
        abort()
    }
}

class ClassB: ClassA {
    override func setValues(_ item: ItemB) { // item have type itemB, but extends ItemA
        item.setValueB("valueB")
        super.setValues(item)
    }
    override func getValues(_ item: ItemA) {
        let item = item as! ItemB
        let array = [item.valueA, item.valueB]
        print(array)
    }
}

我的目标是获得以下结果:

let itemB = ItemB()
ClassB().setValues(itemB)
// print ["valueA", "valueB"]

我无法覆盖类中的函数,因为类型不同,Swift中没有类型继承。我在setValues(_ item: ItemB)ClassB方法中得到了这个错误:

方法不会覆盖其超类中的任何方法

在Java中,这可以使用抽象类和可扩展类型来实现:

abstract class ClassA {
    <T extends ItemA> void setValues(T item) {
    item.setValueA("valueA");
        getValues(item);
    }
    abstract void getValues(MainItem item);
}
swift inheritance override abstract-class extends
2个回答
1
投票

正确的答案取决于泛型:

class ItemA {
    var valueA: String?
    func setValueA(_ value: String?) {
        valueA = value
    }
}

class ItemB: ItemA {
    var valueB: String?
    func setValueB(_ value: String?) {
        valueB = value
    }
}

// Analog of the abstract class
class ClassA {
    func setValues<T : ItemA>(_ item: T) {
        item.setValueA("valueA")
        getValues(item) // call getValues from ClassB
    }
    func getValues(_ item: ItemA) {
        abort()
    }
}

class ClassB: ClassA {
    override func setValues<T : ItemB>(_ item: T) {
        // item have type itemB, but extends ItemA
        item.setValueB("valueB")
        super.setValues(item)
    }
    override func getValues(_ item: ItemA) {
        let item = item as! ItemB
        let array = [item.valueA, item.valueB]
        print(array)
    }
}

核实!如果要打印非可选值,请将其打开。

    let itemB = ItemB()
    ClassB().setValues(itemB)
    // print ["valueA", "valueB"]

1
投票

ClassB.setValues不能接受ItemB类型的参数(即使它是ItemA的子类),因为这样做会违反Liskov替换原则。

ClassB实例需要能够执行ClassA实例所能做的任何事情。其中一个要求是接受ItemAsetValues方法论证。否则,这段代码会发生什么?

let classAInst: ClassA = ClassB()
classAInstance.setValues(ItemA())
© www.soinside.com 2019 - 2024. All rights reserved.