1

Trying to make my OOP fundamentals strong based of objective C. Sorry if my explanation is too long. I have 3 classes in my app as Class A, Class B and Class C objective C classes. I have a property of class A in my implementation of class B i.e. it makes private property of class B.

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

I create an instance of class B in one of my class C methods and try to access class A property through class B's instance in class C.

// 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

To avoid the error I moved the classA property from implementation to header in ClassB.

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

But I am worried that anybody class can create an instance of class B, access classA property and can then use/modify the properties which are part of class A.

Question: Is it a good style to move the classA property to the header file of Class B so I can use it in Class C or should I create a method in Class B which returns me whatever I need from class A? Something like:

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

4 回答 4

2

In ClassB.h:

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

In ClassB.m:

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

Also, strong and readwrite are default modifiers - you can get rid of them. However, they improve code readability.
EDIT: if you want to forbid access for ClassA properties - do the same trick. Suggested above code will forbid only to modify classA property of classB. For ClassA's displayString:
In ClassA.h:

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

In ClassA.m:

@interface ClassA()
  @property (nonatomic, strong, readwrite) NSString *displayString;
@end
于 2013-09-30T20:45:17.550 回答
1

I would suggest a readonly string property in ClassB.h.

ClassB.h:

@property (nonatomic, readonly) NSString *classAString;

ClassB.m:

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

This acts as a "getter" method for the particular string you need, and avoids others getting access to classA.

Edit:

Others suggested adding classA as a readonly property in ClassB.h. This will still allow modification of classA properties, it will only guarantee that classA is not reassigned to another ClassA instance.

于 2013-09-30T20:51:26.793 回答
1

Sounds like you want "framework", not "private" @property() declarations.

To do this, create a file like:

ClassA_Private.h

That contains your @property() declaration.

Then #import "ClassA_Private.h" in both your ClassA.m (prior to the @implementation) and in any subclasses that want to use that @property.

This was a secondary design consideration when creation class extensions; adding the ability to have @property declarations that are fully accessible across subclasses and/or within frameworks without being exposed externally. While you can't create a framework for an iOS targeted application, the same functionality still applies.

于 2013-09-30T21:56:52.513 回答
0

Something like string = objectB.objectA.displayString; is violating the Law of Demeter. Designing according to the Law of Demeter results in more maintainable and adaptable software.

You should always try to not talk to strangers. That is in your example: self talks to objectB and objectB talks to objectA but self shouldn't talk to objectA because it's a stranger.

于 2013-09-30T20:47:44.507 回答