【问题标题】:How can I override a function with various inherited arguments (Swift)如何覆盖具有各种继承参数的函数(Swift)
【发布时间】:2019-09-02 06:50:54
【问题描述】:

如何在 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 中没有类型继承。我在来自ClassBsetValues(_ item: ItemB) 方法中收到此错误:

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

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

abstract class ClassA {
    <T extends ItemA> void setValues(T item) {
    item.setValueA("valueA");
        getValues(item);
    }
    abstract void getValues(MainItem item);
}

【问题讨论】:

    标签: swift inheritance overriding abstract-class extends


    【解决方案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"]
    

    【讨论】:

    • 太棒了!非常感谢!
    • 这个答案并不能解决另一个答案突出显示的问题(将您的ClassB 转换为ClassA 允许您将ItemA 传递给它)。
    • 这是另一个具有另一个功能setValuesgetValues 的任务。只需要另写方法解决即可。
    【解决方案2】:

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

    ClassB 实例需要能够做任何ClassA 实例可以做的事情。其中一项要求是接受 ItemA 参数到其 setValues 方法。否则,这段代码会发生什么?

    let classAInst: ClassA = ClassB()
    classAInstance.setValues(ItemA())
    

    【讨论】:

    • 这并不能解决我的问题。在这种情况下,我会得到["valueA"] 而不是["valueA", "valueB"],因为它只能在ClassAItemA 下工作。
    • 你可以用泛型和java来解决这个问题。我在上面提供了正确答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 2019-01-04
    相关资源
    最近更新 更多