Подтвердить что ты не робот

Свойства только для класса и его подклассов

Можно ли определить свойства, доступные только для класса, в котором они определены, и подклассы класса?

С другой стороны, существует ли способ определить защищенные свойства?

4b9b3361

Ответ 1

Технически, нет. Свойства - это действительно просто методы, и все методы являются общедоступными. Способ, которым мы "защищаем" методы в Objective-C, не позволяет другим людям узнать о них.

Практически, да. Вы можете определить свойства в расширении класса и еще @synthesize их в основном блоке реализации.

Ответ 2

Это возможно с помощью расширения класса (не категории), которое вы включаете в файлы реализации как базового класса, так и подклассов.

Расширение класса определено аналогично категории, но без названия категории:

@interface MyClass ()

В расширении класса вы можете объявить свойства, которые смогут синтезировать поддерживающие ivars (XCode > 4.4, автоматический синтез иваров также работает здесь).

В классе расширения вы можете переопределить/уточнить свойства (изменить readonly на readwrite и т.д.) и добавить свойства и методы, которые будут "видимы" для файлов реализации (но обратите внимание, что свойства и методы на самом деле не являются закрытый и все еще может быть вызван селектором).

Другие предложили использовать отдельный файл заголовка MyClass_protected.h для этого, но это также можно сделать в главном файле заголовка с помощью #ifdef следующим образом:

Пример:

BaseClass.h

@interface BaseClass : NSObject

// foo is readonly for consumers of the class
@property (nonatomic, readonly) NSString *foo;

@end


#ifdef BaseClass_protected

// this is the class extension, where you define 
// the "protected" properties and methods of the class

@interface BaseClass ()

// foo is now readwrite
@property (nonatomic, readwrite) NSString *foo;

// bar is visible to implementation of subclasses
@property (nonatomic, readwrite) int bar;

-(void)baz;

@end

#endif

BaseClass.m

// this will import BaseClass.h
// with BaseClass_protected defined,
// so it will also get the protected class extension

#define BaseClass_protected
#import "BaseClass.h"

@implementation BaseClass

-(void)baz {
    self.foo = @"test";
    self.bar = 123;
}

@end

ChildClass.h

// this will import BaseClass.h without the class extension

#import "BaseClass.h"

@interface ChildClass : BaseClass

-(void)test;

@end

ChildClass.m

// this will implicitly import BaseClass.h from ChildClass.h,
// with BaseClass_protected defined,
// so it will also get the protected class extension

#define BaseClass_protected 
#import "ChildClass.h"

@implementation ChildClass

-(void)test {
    self.foo = @"test";
    self.bar = 123;

    [self baz];
}

@end

Когда вы вызываете #import, он в основном копирует файл .h туда, где вы его импортируете. Если у вас есть #ifdef, он будет включать только код внутри, если установлен #define с этим именем.

В вашем файле .h вы не устанавливаете определение, чтобы любые классы импортировали этот .h, не увидите расширение защищенного класса. В базовом классе и подклассе .m файла вы используете #define перед использованием #import, чтобы компилятор включил расширение защищенного класса.

Ответ 3

Вы можете использовать такой синтаксис в реализации подкласса.

@interface SuperClass (Internal)

@property (retain, nonatomic) NSString *protectedString;

@end

Ответ 4

Вы можете использовать категорию, чтобы достичь своей цели

@interface SuperClass (Protected)

@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIView *topMenuView;
@property (nonatomic, strong) UIView *bottomMenuView;

@end

В подклассе вы импортируете эту категорию в файл .m