#swift #inheritance #overriding #abstract-class #extends
#swift #наследование #переопределение #абстрактный класс #расширяет
Вопрос:
Как переопределить функцию с унаследованным аргументом в 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);
}
Ответ №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. Отлично! Большое вам спасибо!
2. Этот ответ не решает проблему, которую выделяет другой ответ (то, что приведение вашего
ClassB
кClassA
позволяет вам передатьItemA
ему).3. Это другая задача с другими функциями
setValues
иgetValues
. Просто напишите другие методы для ее решения.
Ответ №2:
ClassB.setValues
не могу принять аргумент типа ItemB
(даже если это подкласс ItemA
), потому что это нарушило бы принцип подстановки Лискова.
ClassB
экземпляры должны иметь возможность делать все, что ClassA
могут экземпляры. Одним из таких требований является принятие ItemA
аргументов для его setValues
метода. В противном случае, что произошло бы в этом коде?
let classAInst: ClassA = ClassB()
classAInstance.setValues(ItemA())
Комментарии:
1. Это не решает мою проблему. В этом случае я получу
["valueA"]
вместо["valueA", "valueB"]
, поскольку он будет работать толькоClassA
сItemA
.2. Вы можете решить проблему с помощью дженериков, а также в java. Я предоставил правильный ответ выше.