Objective-C에서 self = [super init]가 0이 아닌지 확인해야하는 이유는 무엇입니까?
Objective-C에서 init 메소드 작성에 대한 일반적인 질문이 있습니다.
초기화를 계속하기 전에 init 메소드가 self = [super init]가 아닌지 확인해야한다는 것이 어디서나 (Apple의 코드, 서적, 오픈 소스 코드 등) 확인됩니다.
init 메소드의 기본 Apple 템플리트는 다음과 같습니다.
- (id) init
{
self = [super init];
if (self != nil)
{
// your code here
}
return self;
}
왜?
init이 언제 nil을 반환 할 것인가? NSObject에서 init를 호출하고 다시 반환하면 실제로 무언가를 망쳐 놓아야합니까? 이 경우 프로그램을 작성하지 않을 수도 있습니다.
클래스의 init 메소드가 nil을 반환하는 것이 일반적입니까? 그렇다면 어떤 경우에 왜 그런가?
예를 들면 다음과 같습니다.
[[NSData alloc] initWithContentsOfFile:@"this/path/doesn't/exist/"];
[[NSImage alloc] initWithContentsOfFile:@"unsupportedFormat.sjt"];
[NSImage imageNamed:@"AnImageThatIsntInTheImageCache"];
... 등등. (참고 : 파일이 존재하지 않으면 NSData에서 예외가 발생할 수 있습니다). nil을 리턴하는 것이 문제가 발생할 때 예상되는 동작이있는 영역이 상당히 많기 때문에 일관성을 위해 nil을 거의 항상 점검하는 것이 표준 관행입니다.
이 특정 관용구는 모든 경우에 작동하기 때문에 표준입니다.
흔하지는 않지만 다음과 같은 경우가 있습니다.
[super init];
... 다른 인스턴스를 반환하므로 자체 할당이 필요합니다.
그리고 nil을 반환하는 경우가 있으므로 nil 확인이 필요하므로 코드가 더 이상 존재하지 않는 인스턴스 변수 슬롯을 초기화하지 않습니다.
결론은 사용하기 위해 문서화 된 올바른 패턴이며, 사용하지 않으면 잘못하고 있다는 것입니다.
대부분의 클래스에서 [super init]의 반환 값이 nil이고 표준 사례에서 권장하는대로 확인한 다음 nil 인 경우 조기에 반환하면 기본적으로 앱이 여전히 올바르게 작동하지 않습니다. 당신도 그 불구하고, 그것에 대해 생각하는 경우 경우 (자기! = 전무) 검사 클래스의 적절한 작동을 위해, 거기, 당신이 실제로 시간의 99.99 % 할 nil이 아닌 될 필요 자체를. 자, 어떤 이유로 든 [super init] 가 nil을 반환했다고 가정합니다. 기본적으로 nil에 대한 검사는 기본적으로 클래스 호출자에게 벅을 전달하는 것으로 가정합니다. 성공한.
기본적으로, 내가 얻는 것은 99.99 %의 시간입니다 .if (self! = nil)는 벅을 전달자에게 넘겨주기 때문에 견고성 측면에서 아무것도 사지 않습니다. 실제로이 문제를 강력하게 처리하려면 실제로 전체 통화 계층 구조를 확인해야합니다. 그럼에도 불구하고 구매할 수있는 유일한 방법은 앱이 더 깨끗하고 견고하게 실패한다는 것입니다. 그러나 여전히 실패 할 것입니다.
라이브러리 클래스가 [super init]의 결과로 임의로 nil을 반환하기로 결정했다면 어쨌든 거의 겁이 나고 라이브러리 클래스 작성자가 구현 실수를 한 것입니다.
앱이 훨씬 제한된 메모리에서 실행될 때 이것은 레거시 코딩 제안에 가깝습니다.
그러나 C 레벨 코드의 경우 일반적으로 여전히 NULL 포인터에 대해 malloc ()의 반환 값을 확인합니다. 반면 Objective-C의 경우, 반대로 증거를 찾을 때까지 if (self! = nil) 검사를 건너 뛸 것이라고 생각합니다. 왜 불일치가 발생합니까?
C 및 malloc 레벨에서 일부 경우 실제로 부분적으로 복구 할 수 있기 때문입니다. Objective-C에서 99.99 %의 경우에 [super init]가 nil을 반환하면 처리하려고해도 기본적으로 f *** ed입니다. 앱이 중단되고 여파를 처리하게 할 수도 있습니다.
이것은 위의 의견에 대한 요약입니다.
수퍼 클래스가를 반환한다고 가정 해 봅시다 nil
. 무슨 일이야?
컨벤션을 따르지 않으면
init
메소드 중간에 코드가 충돌합니다 . ( init
의의가없는 한)
수퍼 클래스가 nil을 리턴 할 수 있음을 모르고 규칙을 따르는 경우 (대부분의 사람들은 여기에서 끝납니다)
인스턴스가이므로 다른 코드가 nil
예상 되기 때문에 코드가 나중에 언젠가 충돌 할 것입니다. 또는 프로그램이 충돌하지 않고 예기치 않게 작동합니다. 이런! 넌 이걸 원해? 모르겠어요 ...
규칙을 따르면 하위 클래스가 nil을 반환하도록 기꺼이 허용
코드 문서 (!)에는 "return ... or nil"이라고 명시해야하며 나머지 코드는이를 처리하기 위해 준비해야합니다. 이제 말이됩니다.
일반적으로 수업이에서 직접 파생되는 경우 NSObject
필요하지 않습니다. 그러나 클래스가 다른 클래스에서 파생되는 경우 이니셜 라이저가을 반환 할 수 있고이 nil
경우 이니셜 라이저가이를 캡처하여 올바르게 작동 할 수 있습니다.
그리고 네, 기록을 위해, 나는 모범 사례를 따르고 모든 수업, 심지어에서 직접 파생 된 수업에 쓰십시오 NSObject
.
You're right, you could often just write [super init]
, but that wouldn't work for a subclass of just anything. People prefer to just memorize one standard line of code and use it all the time, even when it's only sometimes necessary, and thus we get the standard if (self = [super init])
, which takes both the possibility of nil being returned and the possibility of an object other than self
being returned into account.
A common mistake is to write
self = [[super alloc] init];
which returns an instance of the superclass, which is NOT what you want in a subclass constructor/init. You get back an object that does not respond to the subclass methods, which can be confusing, and generate confusing errors about not reponding to methods or identifiers not found, etc.
self = [super init];
is needed if the super class has members (variables or other objects) to initialize first before setting up the subclasses' members. Otherwise the objc runtime initializes them all to 0 or to nil. (unlike ANSI C, which often allocates chunks of memory without clearing them at all)
And yes, base class initialization can fail because of out-of-memory errors, missing components, resource acquisition failures, etc. so a check for nil is wise, and takes less than a few milliseconds.
This is to check that the intialazation worked, the if statement returns true if the init method did not return nil, so its a way to check creation of the object worked correctly. Few reasons i can think of that init might fail maybe its an overriden init method that the super class does not know of or something of the sort, I wouldnt think it is that common though. But if it does happen, its better nothing to happen that a crash i supose so its always checked...
In OS X, it's not as likely for -[NSObject init]
to fail due to memory reasons. The same cannot be said for iOS.
Also, it's good practice for writing when subclassing a class that might return nil
for whatever reason.
'Programing' 카테고리의 다른 글
자식에서 해시 충돌 (0) | 2020.06.02 |
---|---|
.NET 구성 (app.config / web.config / settings.settings) (0) | 2020.06.02 |
Node.js 단위 테스팅 (0) | 2020.06.01 |
Attributes.IsDefined ()에 과부하가없는 이유는 무엇입니까? (0) | 2020.06.01 |
JavaScript에서 왜 2 == [2]입니까? (0) | 2020.06.01 |