Как я могу переопределить функцию с различными унаследованными аргументами (Swift) - PullRequest
0 голосов
/ 11 апреля 2019

Как переопределить функцию с унаследованным аргументом в 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);
}

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Правильный ответ зависит от генериков:

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 голос
/ 11 апреля 2019

ClassB.setValues не может принять аргумент типа ItemB (даже если это подкласс ItemA), потому что это нарушит принцип подстановки Лискова.

ClassB экземпляры нуждаютсячтобы иметь возможность делать все, что могут ClassA экземпляры.Одним из таких требований является принятие ItemA аргументов для его setValues метода.Иначе, что произойдет в этом коде?

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