В Objective-C вы можете в целом повторно объявить свойство readonly
как readwrite
в расширении класса следующим образом:
@interface PubliclyImmutablePrivatelyMutableClass : NSObject
@property (readonly, nonatomic) SomeStateEnum someState;
@end
// In "PubliclyImmutablePrivatelyMutableClass+Private.h"
// or "PubliclyImmutablePrivatelyMutableClass.m"
@interface PubliclyImmutablePrivatelyMutableClass()
@property (readwrite, nonatomic) SomeStateEnum someState;
@end
// In "PubliclyImmutablePrivatelyMutableClass.m"
@implementation PubliclyImmutablePrivatelyMutableClass @end
Однако если я введу свойство в расширение класса как readonly
и попытаюсь повторно объявить его как readwrite
во втором, Xcode 10 Clang выдаст мне ошибку компилятора:
@interface ClassWithPrivateImmutableInternallyMutableProperty : NSObject
// any public API
@end
// In "ClassWithPrivateImmutableInternallyMutableProperty+Private.h"
@interface ClassWithPrivateImmutableInternallyMutableProperty()
@property (readonly, nonatomic) SomePrivateStateEnum somePrivateState;
@end
// In "ClassWithPrivateImmutableInternallyMutableProperty.m"
@interface ClassWithPrivateImmutableInternallyMutableProperty()
@property (readwrite, nonatomic) SomePrivateStateEnum somePrivateState; // error: property has a previous declaration
@end
@implementation ClassWithPrivateImmutableInternallyMutableProperty
// other API
@end
Теперь мне интересно:
Я считаю, что это правильное поведение компилятора.
Во втором примере вы используете две категории продолжения класса с одинаковым именем ()
для объявления одного и того же свойства в двух случаях. Фактически это то же самое, что дважды объявить одно и то же имя свойства в одном и том же расширении.
Обратите внимание, что это отличается от первого примера, в котором свойство сначала объявляется в заголовок, а затем повторно объявляется в одной категории продолжения класса с именем ()
.
Если я прав, то ответ - пометить расширение класса '+ private' именем типа (Private)
вместо ()
:
@interface ClassWithPrivateImmutableInternallyMutableProperty(Private)
А также, если у вас есть какая-либо реализация для частного расширения:
@implementation ClassWithPrivateImmutableInternallyMutableProperty(Private)
Надеюсь, это поможет!
Если вы хотите использовать два продолжения класса, вы не можете объявить свойство с одинаковым именем в обоих. Возможно, используйте внутреннее имя в реализации, например _somePrivateState
, а затем предоставьте геттер в продолжении + private класса, который предоставляет это поддерживающее свойство - (SomePrivateEnum)somePrivateState
.
Если вы поместите имя в круглые скобки, это больше не будет продолжением класса: оно станет простой старой категорией, и они будут вести себя иначе, чем продолжения класса (например, без автоматического синтеза свойств, без возможности добавления переменных экземпляра).