Objective C中的私有v / s公共类属性

时间:2013-09-30 20:29:03

标签: objective-c oop public private-members

尝试根据目标C使我的OOP基础强大。抱歉,如果我的解释太长。 我的应用程序中有3个类作为A类,B类和C类目标C类。 我在B类的实现中有一个A类属性,即它创建了B类的私有属性。

// implementation Class B
@interface ClassB ()
  @property (nonatomic, strong) ClassA *classA;
@end

我在我的一个C类方法中创建了一个B类实例,并尝试通过类C中的B类实例访问A类属性。

// implementation Class C
@interface ClassC ()
  @property (nonatomic, strong) ClassB *classB;
@end

@implementation ClassC
- (void)someMethod
{
  NSString *string = [[NSString alloc] init];
  classB = [[ClassB alloc] init];
  string = classB.classA.displayString; //get an error here - ClassB doesn't have classA.
}
@end

为了避免错误,我将classA属性从实现移动到了ClassB中的头文件。

// header Class B
@interface ClassB : NSObject
  @property (nonatomic, strong) ClassA *classA;
@end

但我担心任何人都可以创建一个B类实例,访问classA属性,然后可以使用/修改属于A类的属性。

问题: 将classA属性移动到B类的头文件是一种好方法,所以我可以在C类中使用它,或者我应该创建一个方法在B级,我从A级回报我需要的东西?类似的东西:

@implementation ClassB
- (NSString*)displayStringOfClassA
{
  classA = [[ClassA alloc] init];
  return self.classA.displayString;
}
@end

4 个答案:

答案 0 :(得分:1)

在ClassB.h中:

@interface ClassB: NSObject
  @property (nonatomic, strong, readonly) ClassA *classA;
@end

在ClassB.m中:

@interface ClassB()
  @property (nonatomic, strong, readwrite) ClassA *classA;
@end

此外,strongreadwrite是默认修饰符 - 您可以摆脱它们。但是,它们提高了代码的可读性 编辑:如果你想禁止访问ClassA属性 - 做同样的技巧。建议上面的代码将禁止修改classB的classA属性。对于ClassA的displayString:
 在ClassA.h中:

@interface ClassA: NSObject
  @property (nonatomic, strong, readonly) NSString *displayString;
@end

在ClassA.m中:

@interface ClassA()
  @property (nonatomic, strong, readwrite) NSString *displayString;
@end

答案 1 :(得分:1)

听起来你想要“框架”,而不是“私人”@property()声明。

为此,请创建如下文件:

ClassA_Private.h

包含您的@property()声明。

然后在#import "ClassA_Private.h"ClassA.m之前)和任何想要使用@implementation的子类中@property。{/ p>

这是创建类扩展时的二次设计考虑因素;添加具有@property声明的功能,这些声明可以跨子类和/或在框架内完全访问,而不会在外部公开。虽然您无法为iOS目标应用程序创建框架,但仍然适用相同的功能。

答案 2 :(得分:0)

string = objectB.objectA.displayString;之类的内容违反了Law of Demeter。根据Demeter法则进行设计可以获得更易维护和适应性更强的软件。

你应该总是试图不要与陌生人交谈。在您的示例中:selfobjectB进行对话,objectBobjectA进行对话,但self不应与objectA对话,因为它是{陌生人。

答案 3 :(得分:0)

我建议在ClassB.h中使用readonly字符串属性。

ClassB.h:

@property (nonatomic, readonly) NSString *classAString;

ClassB.m:

- (NSString *) classAString
{
   return self.classA.displayString;
}

这可以作为您需要的特定字符串的“getter”方法,并避免其他人访问classA。

编辑:

其他人建议在ClassB.h中添加classA作为readonly属性。这仍然允许修改classA属性,它只能保证classA不会被重新分配给另一个ClassA实例。