I have a class which is derived from a base class that has a property.
@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
I wrote a swift extension to make the property available in the base class.
extension TestBase {
var test: TestProp? {
guard let testClass = self as? TestClass else { return nil }
return testClass.test
}
}
The problem is testClass.test
calls the getter from TestBase
instead of TestClass
. This results in infinite recursion that smashes the stack.
Is this a defect? Is there a way I can make it work?
UPDATE
When I first thought of it, I was hoping I could treat it like a function.
extension TestBase {
var test: TestProp? {
return nil
}
}
and the following would happen:
func callback(_ testBase: TestBase) {
guard let prop = testBase.prop else { return }
…
}
callback(TestBase()) // uses TestBase.prop
callback(TestClass()) // uses TestClass.prop
That didn't work. The actual behavior was
callback(TestBase()) // uses TestBase.prop
callback(TestClass()) // uses TestBase.prop
Properties don't work like functions. So the extension
extension TestBase {
var test: TestProp? {
guard let testClass = self as? TestClass else { return nil }
return testClass.test
}
}
was my attempt to force the use of TestCase.prop
.
I'm trying to avoid
func callback(_ testBase: TestBase) {
guard let prop = (testBase as? TestClass)?.prop else { return }
…
}
FINAL UPDATE
I discovered a method that worked, see my answer if your are interested.
However, it's just not worth it. The solution was too complex. I created a private global function.
private func prop(_ testBase: TestBase) -> TestProp {
return (testBase as? TestClass)?.prop
}
then in the callbacks
func callback(_ testBase: TestBase) {
guard let prop = prop(testBase) else { return }
…
}
Not object oriented, but simple.