Apple의 Objective-C 2.0 문서를 읽고있는 Java 개발자로서 ” 메시지를 nil로 전송 “이 의미 하는 바가 무엇인지 궁금 합니다. 실제로 유용하다는 것은 말할 것도 없습니다. 문서에서 발췌 :
Cocoa에는이 사실을 활용하는 몇 가지 패턴이 있습니다. 메시지에서 nil로 반환 된 값도 유효 할 수 있습니다.
- 메서드가 객체, 포인터 유형, sizeof (void *)보다 작거나 같은 크기의 정수 스칼라, float, double, long double 또는 long long을 반환하면 nil로 전송 된 메시지는 0을 반환합니다. .
- 메서드가 Mac OS X ABI 함수 호출 가이드에 정의 된대로 레지스터에 반환되는 구조체를 반환하는 경우 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라는 것입니다 – 그냥하지 않습니다 할 것을. 이렇게하면 “무를 확인하고 참이면 메시지를 보내지 마십시오”코드도 많이 제거됩니다. ( “만약 그것이 그것을 받아들이면 그것을 구현한다”개념은 또한 일종의 자바 인터페이스와 비슷한 프로토콜 을 생성 할 수있게 해준다 . 클래스가 명시된 메소드를 구현하면 프로토콜을 준수한다는 선언이다.)
그 이유는 컴파일러를 행복하게 유지하는 것 외에는 아무것도하지 않는 원숭이 코드를 제거하기 위해서입니다. 예, 한 번 더 메서드 호출의 오버 헤드가 발생하지만 프로그래머 시간 을 절약 할 수 있습니다. . 이는 CPU 시간보다 훨씬 더 비싼 리소스입니다. 또한 애플리케이션에서 더 많은 코드와 조건부 복잡성을 제거하고 있습니다.
비추천 사용자를위한 설명 : 이것이 좋은 방법이 아니라고 생각할 수 있지만 언어가 구현되는 방식 이며 Objective-C에서 권장되는 프로그래밍 관용구 입니다 (Stanford iPhone 프로그래밍 강의 참조).
답변
의미하는 바는 objc_msgSend가 nil 포인터에서 호출 될 때 런타임이 오류를 생성하지 않는다는 것입니다. 대신 (종종 유용한) 값을 반환합니다. 부작용이있을 수있는 메시지는 아무것도하지 않습니다.
대부분의 기본값이 오류보다 더 적절하기 때문에 유용합니다. 예를 들면 :
[someNullNSArrayReference count] => 0
즉, nil은 빈 배열로 보입니다. nil NSView 참조를 숨기는 것은 아무것도하지 않습니다. 핸디, 응?
답변
문서의 인용문에는 두 가지 개별 개념이 있습니다. 문서에서 더 명확하게 설명하면 더 좋을 수 있습니다.
Cocoa에는이 사실을 활용하는 몇 가지 패턴이 있습니다.
메시지에서 nil로 반환 된 값도 유효 할 수 있습니다.
전자가 여기서 더 관련이있을 수 있습니다. 일반적으로 nil
코드를보다 간단하게 만들기 위해 메시지를 보낼 수 있습니다. 모든 곳에서 null 값을 확인할 필요가 없습니다. 표준 예제는 아마도 접근 자 메서드 일 것입니다.
- (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) 이상을 실행하는 경우
반환 유형으로 nil에 대한 메시지 | 반환 최대 64 비트의 정수 | 0 long double까지의 부동 소수점 | 0.0 포인터 | 무 구조체 | {0} 모든 _ 복합 유형 | {0, 0}
답변
이는 안전을 위해 모든 곳에서 nil 객체를 확인할 필요가 없다는 것을 의미합니다. 특히 :
[someVariable release];
또는 언급했듯이 다양한 count 및 length 메서드는 nil 값이있을 때 모두 0을 반환하므로 nil에 대한 추가 검사를 추가 할 필요가 없습니다.
if ( [myString length] > 0 )
아니면 이거:
return [myArray count]; // say for number of rows in a table