6

나는 보통이 같은 자신의 getter 메소드 내 @property 객체 게으른 인스턴스화 :재정의 속성 게터

@interface MyGenericClass : UIViewController 
@property(nonatomic, readonly) UIImageView *infoImageView 
// ... 

@implementation GenericClass 

- (UIImageView *)infoImageView 
{ 
    if (!_infoImageView) { 
     _infoImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"PlaceholderInfoImage"]]; 
    } 
    return _infoImageView; 
} 

그러나 서브 클래스, 나는 종종 싶습니다은 @properties의 일부를 오버라이드 (override) 더 많은 서브 클래스에 속한다. 그래서 같은 인스턴스화를 변경 할 싶습니다

@interface MySpecificSubclass : MyGenericClass 
//... 

@implementation MySpecificSubclass 

- (UIImageView *)infoImageView 
{ 
    if (!_infoImageView) { 
     _infoImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"SpecialInfoImage"]]; 
    } 
    return _infoImageView; 
} 

을하지만, 서브 클래스가 _infoImageView 바르 액세스 할 수 없기 때문에 즉, 수 없습니다.

나쁜 스타일을하려고합니까? 또는 이에 대한 일반적인 해결책/모범 사례가 있습니까? 내가 볼 수있는 유일한 해결책은 캡슐화 원칙을 위반하는 것처럼 느껴지는 iVar를 공개하는 것입니다 ...

이렇게 아주 기본적인 질문이므로 이미 수백만 개의 답변이 있어야합니다 내가 찾을 수있는 시간 동안 모두 Objective-C: Compiler error when overriding a superclass getter and trying to access ivar 이지만 해결책이 없습니다.

답변

8

헤더 파일의 보호 된 변수로 _infoImageView을 속성과 함께 선언 할 수 있습니다. 또 다른 아이디어는 공개 defaultImageView 메서드를 만들어 게으른 게터 내부에서 호출하는 것입니다. 이 같은 뭔가 :

@interface MyGenericClass : UIViewController 
@property (nonatomic, readonly) UIImageView *infoImageView 

...

@implementation GenericClass 

- (UIImageView *)infoImageView 
{ 
    if (!_infoImageView) { 
     _infoImageView = [self defaultImageView]; 
    } 
    return _infoImageView; 
} 

- (UIImageView *)defaultImageView 
{ 
    return [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"PlaceholderInfoImage"]]; 
} 

...

@interface MySpecificSubclass : MyGenericClass 

...

@implementation MySpecificSubclass 

- (UIImageView *)defaultImageView 
{ 
    return [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SpecialInfoImage"]]; 
} 
2

다른 대답이 말했듯하는 선언 헤더의 보호 된 변수. 새로운 컴파일러는 일반적으로 필요하지 않지만이 경우에는 실제로 도움이됩니다!

@interface MyGenericClass : UIViewController{ 
    UIImageView *_infoImageView 
} 
@property(nonatomic, readonly) UIImageView *infoImageView