문제

Apple의 Objective-C 2.0 문서를 읽고 있는 Java 개발자로서:나는 궁금해 "nil에게 메시지 보내기"는 - 그것이 실제로 얼마나 유용한지는 말할 것도 없고요.문서에서 발췌:

코코아에는이 사실을 활용하는 몇 가지 패턴이 있습니다.메시지에서 nil로 반환 된 값도 유효 할 수 있습니다.

  • 메서드가 개체, 포인터 형식, 정수 스칼라를 반환하는 경우 다음보다 작거나 같은 크기 sizeof(void*), float, double, a long double 또는 long long이면 nil에 보낸 메시지는 0을 반환합니다.
  • 메서드가 Mac OS X ABI 함수에 정의된 구조체를 반환하는 경우 반납할 통화 안내 registers를 등록한 다음 nil로 보낸 메시지 의 모든 필드에 대해 0.0을 반환합니다. 데이터 구조.다른 구조체 데이터 형식은 0으로 채워지지 않습니다.
  • 메소드가 앞서 언급 한 값 이외의 다른 것을 반환하면 NIL에 전송 된 메시지의 반환 값은 정의되지 않습니다.

Java가 내 두뇌로 위의 설명을 이해하지 못하게 만들었나요?아니면 이것을 유리처럼 투명하게 만드는 뭔가가 내가 놓친 것이 있습니까?

Objective-C의 메시지/수신자에 대한 아이디어는 얻었지만, 수신자에 대해 혼란스럽습니다. nil.

도움이 되었습니까?

해결책

글쎄, 나는 그것이 매우 인위적인 예를 사용하여 설명될 수 있다고 생각합니다.ArrayList의 모든 요소를 ​​인쇄하는 Java 메소드가 있다고 가정해 보겠습니다.

void foo(ArrayList list)
{
    for(int i = 0; i < list.size(); ++i){
        System.out.println(list.get(i).toString());
    }
}

이제 해당 메소드를 다음과 같이 호출하면:someObject.foo(NULL);목록에 액세스하려고 하면 아마도 NullPointerException이 발생하게 될 것입니다. 이 경우에는 list.size()를 호출할 때입니다.이제 그런 NULL 값을 사용하여 someObject.foo(NULL)을 호출하지 않을 것입니다.그러나 someObject.foo(otherObject.getArrayList());와 같은 ArrayList 생성 오류가 발생하는 경우 NULL을 반환하는 메서드에서 ArrayList를 얻었을 수도 있습니다.

물론 다음과 같이 하면 문제가 발생합니다.

ArrayList list = NULL;
list.size();

이제 Objective-C에는 동일한 방법이 있습니다.

- (void)foo:(NSArray*)anArray
{
    int i;
    for(i = 0; i < [anArray count]; ++i){
        NSLog(@"%@", [[anArray objectAtIndex:i] stringValue];
    }
}

이제 다음 코드가 있다면:

[someObject foo:nil];

Java가 NullPointerException을 생성하는 것과 동일한 상황이 있습니다.nil 객체는 [anArray count]에서 먼저 액세스됩니다. 그러나 NullPointerException을 발생시키는 대신 Objective-C는 위의 규칙에 따라 단순히 0을 반환하므로 루프가 실행되지 않습니다.그러나 설정된 횟수만큼 실행되도록 루프를 설정하면 먼저 [anArray objectAtIndex:i]에서 anArray에 메시지를 보냅니다.이 역시 0을 반환하지만 objectAtIndex 이후:포인터를 반환하고 0에 대한 포인터가 nil/NULL인 경우 NSLog는 루프를 통해 매번 nil로 전달됩니다.(NSLog는 메소드가 아닌 함수이지만 nil NSString이 전달되면 (null)을 인쇄합니다.

어떤 경우에는 프로그램에 문제가 있음을 즉시 알 수 있지만 예외를 포착하지 않으면 프로그램이 중단되므로 NullPointerException을 사용하는 것이 더 좋습니다.(C에서는 이런 방식으로 NULL을 역참조하려고 하면 프로그램이 충돌하게 됩니다.) Objective-C에서는 대신 잘못된 런타임 동작이 발생할 수 있습니다.그러나 0/nil/NULL/0으로 된 구조체를 반환하는 경우 중단되지 않는 메서드가 있는 경우 개체나 매개 변수가 nil인지 확인하지 않아도 됩니다.

다른 팁

메시지 nil 아무것도하지 않고 돌아옵니다 nil, Nil, NULL, 0, 또는 0.0.

다른 모든 게시물은 정확하지만 여기서 중요한 개념 일 수도 있습니다.

Objective-C 메소드 호출에서 선택기를 수락 할 수있는 객체 참조는 해당 선택기의 유효한 대상입니다.

이것은 "유형 X의 대상 객체입니까?"를 많이 절약합니다. 코드 - 수신 객체가 선택기를 구현하는 한 전혀 차이가 없습니다 그것은 어떤 수업입니까! nil 선택기를 수락하는 nsobject입니다. 하다 아무것. 이렇게하면 "NIL을 확인하고 메시지를 보내지 마십시오"코드도 많이 제거됩니다. ( "그것이 그것을 받아들이면, 그것을 구현한다"개념은 또한 당신이 만들 수있는 것입니다. 프로토콜, Java 인터페이스와 비슷합니다. 클래스가 명시된 방법을 구현하면 프로토콜을 준수한다는 선언.)

그 이유는 컴파일러를 행복하게 유지하는 것 외에는 아무것도하지 않는 원숭이 코드를 제거하기 때문입니다. 예, 한 가지 메소드 호출의 오버 헤드를 얻지 만 저장합니다. 프로그래머 시간, CPU 시간보다 훨씬 비싼 리소스입니다. 또한 응용 프로그램에서 더 많은 코드와 더 많은 조건부 복잡성을 제거하고 있습니다.

DownVoters를 명확하게 설명 : 이것이 좋은 방법이 아니라고 생각할 수도 있지만 언어가 구현되는 방식이며 권장되는 프로그래밍 관용구입니다. 대상 c (Stanford iPhone 프로그래밍 강의 참조).

그것이 의미하는 바는 런타임이 NIL 포인터에서 OBJC_MSGSEND가 호출 될 때 오류가 발생하지 않는다는 것입니다. 대신 일부 (종종 유용한) 값을 반환합니다. 부작용이있는 메시지는 아무것도하지 않습니다.

대부분의 기본값이 오류보다 더 적합하기 때문에 유용합니다. 예를 들어:

[someNullNSArrayReference count] => 0

즉, NIL은 빈 배열 인 것 같습니다. nil nsview 참조를 숨기는 것은 아무것도하지 않습니다. 편리 해요?

문서의 인용에는 두 가지 개별 개념이 있습니다. 문서가 더 명확하게 만들면 더 나을 수 있습니다.

코코아에는이 사실을 활용하는 몇 가지 패턴이 있습니다.

메시지에서 NIL로 반환 된 값도 유효 할 수 있습니다.

전자는 아마도 여기에서 더 관련성이있을 것입니다 : 일반적으로 메시지를 보낼 수 있습니다. nil 코드를보다 간단하게 만듭니다. 어디에서나 널 값을 확인할 필요가 없습니다. 표준 예는 아마도 액세서 방법 일 것입니다.

- (void)setValue:(MyClass *)newValue {
    if (value != newValue) { 
        [value release];
        value = [newValue retain];
    }
}

메시지를 보내는 경우 nil 유효하지 않았 으며이 방법은 더 복잡 할 것입니다. value 그리고 newValue 그렇지 않습니다 nil 메시지를 보내기 전에.

후자의 지점 (그 값은 메시지에서 반환 된 값 nil 그러나 일반적으로 유효합니다)는 전자에 승수 효과를 추가합니다. 예를 들어:

if ([myArray count] > 0) {
    // do something...
}

이 코드는 다시 수표가 필요하지 않습니다 nil 가치와 자연스럽게 흐릅니다 ...

이 모든 것은 nil 어느 정도 비용이 듭니다. 값이 될 가능성을 고려하지 않았기 때문에 어떤 단계에서 독특한 방식으로 실패 할 가능성이 있습니다. nil.

에서 그렉 파커'에스 대지:

LLVM 컴파일러 3.0 (Xcode 4.2) 이상을 실행하는 경우

Messages to nil with return type | return
Integers up to 64 bits           | 0
Floating-point up to long double | 0.0
Pointers                         | nil
Structs                          | {0}
Any _Complex type                | {0, 0}

그것은 종종 안전을 위해 모든 곳에서 NIL 물체를 확인할 필요가 없다는 것을 의미합니다.

[someVariable release];

또는 언급 한 바와 같이, NIL 값이있을 때 다양한 카운트 및 길이 메소드가 모두 반환되므로 NIL에 대한 추가 점검을 추가 할 필요가 없습니다.

if ( [myString length] > 0 )

아니면 이거:

return [myArray count]; // say for number of rows in a table

"수신기는 nil"에 대해 생각하지 마십시오. 나는 동의한다 ~이다 꽤 이상합니다. NIL에 메시지를 보내는 경우 수신기가 없습니다. 당신은 단지 메시지를 아무것도 보내지 않습니다.

이를 다루는 방법 Java와 Objective-C의 철학적 차이 : Java에서는 오류입니다. Objective-C에서는 No-OP입니다.

NIL로 전송되고 반환 값이 크기가 크기가 큰 OBJC 메시지 (void*) PowerPC 프로세서에서 정의되지 않은 값을 생성합니다. 그 외에도 이러한 메시지는 인텔 프로세서에서 크기가 8 바이트보다 큰 스트러크 필드에서 정의되지 않은 값을 반환합니다. Vincent Gable은 이것에 대해 이것을 멋지게 묘사했습니다 블로그 게시물

다른 답변 중 어느 것도 이것을 명확하게 언급 한 적이 없다고 생각합니다. Java에 익숙하다면 Mac OS X의 Objective-C가 예외 처리 지원이 있지만 선택적 언어 기능이라는 점을 명심해야합니다. 컴파일러 플래그로 켜지거나 끕니다. 내 생각 에이 "메시지 보내기"라는 디자인은 nil 안전합니다. "언어로 예외 처리 지원을 포함시키는 것을 초행하고 비슷한 목표를 염두에두고 수행되었습니다. 방법은 반환 할 수 있습니다. nil 오류를 나타내고 메시지를 보내는 이후 nil 일반적으로 반환됩니다 nil 결과적으로 오류 표시가 코드를 통해 전파 될 수 있으므로 모든 메시지에서 확인할 필요가 없습니다. 중요한 곳에서만 확인하면됩니다. 나는 개인적으로 예외 전파와 취급 이이 목표를 다루는 더 좋은 방법이라고 생각하지만 모든 사람이 그것에 동의 할 수있는 것은 아닙니다. (반면에, 나는 예를 들어, 방법이 던질 수있는 예외를 선언해야한다는 Java의 요구 사항이 마음에 들지 않습니다. 구문 적으로 코드 전체에서 예외 선언을 전파합니다. 그러나 그것은 또 다른 토론입니다.)

관련 질문에 대해 비슷하지만 더 긴 답변을 게시했습니다. "모든 객체 생성이 객관적인 C에서 필요하다고 주장 하는가?" 자세한 내용을 원한다면.

C는 원시 값의 경우 0으로 0으로, 포인터의 경우 널 (포인터 컨텍스트에서 0에 해당).

Objective-C는 NIL을 추가하여 C의 아무것도 표현하지 않습니다. Nil은 아무것도 대상 포인터입니다. Semantically는 Null과 구별되지만 기술적으로 서로 동등합니다.

새로 알로 된 nsobjects는 내용을 0으로 설정하여 생명을 시작합니다. 이것은 다른 객체에 대한 객체가있는 모든 포인터가 nil로 시작하므로 예를 들어 init 메소드에서 self를 설정하는 것이 불필요하다는 것을 의미합니다.

그러나 NIL의 가장 주목할만한 행동은 메시지를 전송할 수 있다는 것입니다.

C ++ (또는 Java)와 같은 다른 언어에서는 프로그램이 충돌하지만 Objective-C에서는 NIL의 메소드를 호출하면 0 값을 반환합니다. 이것은 무엇이든하기 전에 NIL을 점검해야 할 필요성이 없기 때문에 표현을 크게 단순화합니다.

// For example, this expression...
if (name != nil && [name isEqualToString:@"Steve"]) { ... }

// ...can be simplified to:
if ([name isEqualToString:@"Steve"]) { ... }

Objective-C에서 NIL의 작동 방식을 알고 있으면이 편의성이 기능이 될 수 있으며 응용 프로그램에 숨어있는 버그가 아닙니다. NIL 값이 원치 않는 경우, 조용히 실패하기 위해 일찍 돌아 오거나 NSParameterAssert를 추가하여 예외를 던지기 위해 NIL 값이 원치 않는 경우에 대해 보호하십시오.

원천:http://nshipster.com/nil/ https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/ocobjectsclasses.html (NIL에 메시지 보내기).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top