Ошибка "свойство имеет предыдущее объявление" в расширении класса: ошибка или функция?

В 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

Теперь мне интересно:

  • Ошибка компилятора - это ошибка / регресс в Clang или преднамеренная функция?
  • Если это ошибка, есть ли другой обходной путь, кроме ручного внедрения установщика?
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
1 200
1

Ответы 1

Я считаю, что это правильное поведение компилятора.

Во втором примере вы используете две категории продолжения класса с одинаковым именем () для объявления одного и того же свойства в двух случаях. Фактически это то же самое, что дважды объявить одно и то же имя свойства в одном и том же расширении.

Обратите внимание, что это отличается от первого примера, в котором свойство сначала объявляется в заголовок, а затем повторно объявляется в одной категории продолжения класса с именем ().

Если я прав, то ответ - пометить расширение класса '+ private' именем типа (Private) вместо ():

@interface ClassWithPrivateImmutableInternallyMutableProperty(Private)

А также, если у вас есть какая-либо реализация для частного расширения:

@implementation ClassWithPrivateImmutableInternallyMutableProperty(Private)

Надеюсь, это поможет!

Если вы поместите имя в круглые скобки, это больше не будет продолжением класса: оно станет простой старой категорией, и они будут вести себя иначе, чем продолжения класса (например, без автоматического синтеза свойств, без возможности добавления переменных экземпляра).

danyowdee 01.11.2018 11:15

Если вы хотите использовать два продолжения класса, вы не можете объявить свойство с одинаковым именем в обоих. Возможно, используйте внутреннее имя в реализации, например _somePrivateState, а затем предоставьте геттер в продолжении + private класса, который предоставляет это поддерживающее свойство - (SomePrivateEnum)somePrivateState.

ncke 01.11.2018 11:45

Другие вопросы по теме