У меня есть класс, производный от базового класса, который имеет свойство.
@interface TestProp: NSObject
@property (nonnull, nonatomic) NSString *prop;
@end
@interface TestBase: NSObject
@end
@interface TestClass: TestBase
- (nullable TestProp *)testGetter;
- (void)testSetter:(nullable TestProp *)test;
@property (nullable, nonatomic, readonly, getter=testGetter) TestProp *test;
@end
@implementation TestProp
@end
@implementation TestBase
@end
@implementation TestClass { TestProp *_test; }
- (TestProp *)testGetter { return _test; }
- (void)testSetter:(TestProp *)test { _test = test; }
@end
Я написал быстрое расширение, чтобы сделать свойство доступным в базовом классе.
extension TestBase {
var test: TestProp? {
guard let testClass = self as? TestClass else { return nil }
return testClass.test
}
}
Проблема в том, что testClass.test
вызывает геттер из TestBase
вместо TestClass
. Это приводит к бесконечной рекурсии, которая разбивает стек.
Это дефект? Есть ли способ, которым я могу заставить это работать?
UPDATE
Когда я впервые подумал об этом, я надеялся, что смогу воспринимать это как функцию.
extension TestBase {
var test: TestProp? {
return nil
}
}
и произойдет следующее:
func callback(_ testBase: TestBase) {
guard let prop = testBase.prop else { return }
…
}
callback(TestBase()) // uses TestBase.prop
callback(TestClass()) // uses TestClass.prop
Это не сработало. Фактическое поведение было
callback(TestBase()) // uses TestBase.prop
callback(TestClass()) // uses TestBase.prop
Свойства не работают как функции. Так что расширение
extension TestBase {
var test: TestProp? {
guard let testClass = self as? TestClass else { return nil }
return testClass.test
}
}
была моей попыткой заставить TestCase.prop
.
Я пытаюсь избежать
func callback(_ testBase: TestBase) {
guard let prop = (testBase as? TestClass)?.prop else { return }
…
}
ФИНАЛЬНОЕ ОБНОВЛЕНИЕ
Я обнаружил метод, который работал, смотрите мой ответ, если вам интересно.
Однако, оно того не стоит. Решение было слишком сложным. Я создал частную глобальную функцию.
private func prop(_ testBase: TestBase) -> TestProp {
return (testBase as? TestClass)?.prop
}
затем в обратных вызовах
func callback(_ testBase: TestBase) {
guard let prop = prop(testBase) else { return }
…
}
Не объектно-ориентированный, а простой.