Objective-C가 개인 메소드를 지원하지 않는 이유는 무엇입니까?
Objective-C 에서 semi-private 메소드를 선언하는 여러 가지 전략을 보았지만 실제로 개인 메소드를 만드는 방법은 없습니다. 동의합니다. 그러나 왜 그렇습니까? 내가 본질적으로 말한 모든 설명은 "당신은 할 수 없지만 근사치입니다."
ivars
범위를 제어하는 (멤버)에 적용되는 키워드는 여러 가지가 있습니다 (예 : @private
, @public
) @protected
. 왜 메소드에 대해서도 이것을 할 수 없습니까? 런타임이 지원할 수있는 것 같습니다. 내가 놓친 근본적인 철학이 있습니까? 고의입니까?
대답은 ... 음 ... 간단합니다. 사실 단순성과 일관성.
Objective-C는 메소드 디스패치 순간에 순전히 역동적입니다. 특히, 모든 메소드 디스패치는 다른 모든 메소드 디스패치와 동일한 동적 메소드 분석 지점을 통과합니다. 런타임시 모든 메소드 구현은 동일한 노출을 가지며 Objective-C 런타임에서 제공하는 메소드 및 선택기와 함께 작동하는 모든 API는 모든 메소드에서 동일하게 작동합니다.
많은 사람들이 (여기 및 다른 질문 모두에서) 대답했듯이 컴파일 타임 개인 메소드가 지원됩니다. 클래스가 공개적으로 사용 가능한 인터페이스에서 메소드를 선언하지 않으면 코드에 관한 한 해당 메소드가 존재하지 않을 수 있습니다. 즉, 프로젝트를 적절하게 구성하여 컴파일 타임에 원하는 다양한 가시성 조합을 모두 달성 할 수 있습니다.
동일한 기능을 런타임에 복제하면 이점이 거의 없습니다. 엄청난 양의 복잡성과 오버 헤드가 추가됩니다. 그리고 그 모든 복잡성에도 불구하고 가장 캐주얼 한 개발자 이외의 모든 사용자가 "비공개"메서드를 실행하는 것을 여전히 막을 수는 없습니다.
편집 : 내가 알아 차린 가정 중 하나는 개인 메시지가 런타임을 거쳐야 할 가능성이 있으며 결과적으로 오버 헤드가 커질 것입니다. 이것이 사실입니까?
그렇습니다. 클래스의 구현자가 구현에서 모든 Objective-C 기능 세트를 사용하고 싶지 않다고 가정 할 이유가 없으므로 동적 디스패치가 발생해야합니다. 그러나
objc_msgSend()
컴파일러가 전용 메소드 라는 것을 알 수 있기 때문에 전용 메소드를의 특수 변형으로 디스패치 할 수없는 특별한 이유는 없습니다 . 즉, 개인 전용 메소드 테이블을Class
구조 에 추가하여이를 달성 할 수 있습니다 .개인 메소드 가이 검사를 단락하거나 런타임을 건너 뛸 수있는 방법이 없습니까?
런타임을 건너 뛸 수는 없지만 런타임 은 반드시 개인 메소드를 검사 할 필요가 없습니다 .
즉, 제 3자가
objc_msgSendPrivate()
해당 객체의 구현 외부에서 의도적으로 객체를 호출 할 수 없었던 이유는 없으며 , 일부 작업 (예 : KVO)이이를 수행해야합니다. 실제로 개인 메서드의 선택자 앞에 접두사를 붙이거나 인터페이스 헤더에 언급하지 않는 것보다는 실제로는 관례에 불과합니다.
그러나 그렇게하는 것은 언어의 순수한 역 동성을 약화시킬 것입니다. 더 이상 모든 메소드 디스패치가 동일한 디스패치 메커니즘을 거치지는 않습니다. 대신 대부분의 방법이 한 가지 방식으로 작동하고 소수의 소수만 다른 상황에 처하게됩니다.
Cocoa에는 Objective-C의 일관된 역 동성을 기반으로 구축 된 많은 메커니즘이 있기 때문에 런타임을 넘어 확장됩니다. 예를 들어, Key Value Coding과 Key Value Observation은 개인용 메서드 (악용 가능한 허점을 만들어서)를 지원하도록 크게 수정되거나 개인용 메서드가 호환되지 않습니다.
런타임은이를 지원할 수 있지만 비용은 엄청납니다. 전송 된 모든 선택기는 해당 클래스에 대해 개인용인지 공용인지 확인해야합니다. 그렇지 않으면 각 클래스가 두 개의 개별 디스패치 테이블을 관리해야합니다. 이 보호 수준은 컴파일 타임에 수행되므로 인스턴스 변수의 경우와 동일하지 않습니다.
또한 런타임은 개인 메시지의 발신자가 수신자와 동일한 클래스인지 확인해야합니다. 개인 메소드를 우회 할 수도 있습니다. 클래스가 사용 instanceMethodForSelector:
되면 IMP
개인 메소드를 직접 호출하기 위해 다른 클래스에 리턴 을 줄 수 있습니다.
개인 메소드가 메시지 디스패치를 우회 할 수 없습니다. 다음 시나리오를 고려하십시오.
클래스
AllPublic
에는 공개 인스턴스 메소드가 있습니다doSomething
다른 클래스
HasPrivate
에는 개인 인스턴스 메소드가 있습니다.doSomething
당신은 모두의 인스턴스의 수를 포함하는 배열을 생성
AllPublic
하고HasPrivate
다음과 같은 루프가 있습니다.
for (id anObject in myArray) [anObject doSomething];
within에서 해당 루프를 실행
AllPublic
하면 런타임doSomething
에서HasPrivate
인스턴스 전송을 중지해야 하지만HasPrivate
클래스 내부에있는 경우이 루프를 사용할 수 있습니다 .
지금까지 게시 된 답변은 철학적 관점에서 질문에 대답하는 데 도움이됩니다. 따라서 더 실용적인 이유를 제시하겠습니다. 언어의 의미를 변경하면 얻을 수있는 것은 무엇입니까? 개인 메소드를 효과적으로 "숨길"정도로 간단합니다. 예를 들어, 헤더 파일에 다음과 같이 선언 된 클래스가 있다고 가정하십시오.
@interface MyObject : NSObject {}
- (void) doSomething;
@end
"비공개"메소드가 필요한 경우이를 구현 파일에 넣을 수도 있습니다.
@interface MyObject (Private)
- (void) doSomeHelperThing;
@end
@implementation MyObject
- (void) doSomething
{
// Do some stuff
[self doSomeHelperThing];
// Do some other stuff;
}
- (void) doSomeHelperThing
{
// Do some helper stuff
}
@end
Sure, it's not quite the same as C++/Java private methods, but it's effectively close enough, so why alter the semantics of the language, as well as the compiler, runtime, etc., to add a feature that's already emulated in an acceptable way? As noted in other answers, the message-passing semantics -- and their reliance on runtime reflection -- would make handling "private" messages non-trivial.
The easiest solution is just to declare some static C functions in your Objective-C classes. These only have file scope as per the C rules for the static keyword and because of that they can only be used by methods in that class.
No fuss at all.
Yes, it can be done without affecting the runtime by utilizing a technique already employed by the compiler(s) for handling C++: name-mangling.
It hasn't been done because it hasn't been established that it would solve some considerable difficulty in the coding problem space that other techniques (e.g., prefixing or underscoring) are able to circumvent sufficiently. IOW, you need more pain to overcome ingrained habits.
You could contribute patches to clang or gcc that add private methods to the syntax and generated mangled names that it alone recognized during compilation (and promptly forgot). Then others in the Objective-C community would be able to determine whether it was actually worthwhile or not. It's likely to be faster that way than trying to convince the developers.
Essentially, it has to do with Objective-C's message-passing form of method calls. Any message can be sent to any object, and the object chooses how to respond to the message. Normally it will respond by executing the method named after the message, but it could respond in a number of other ways too. This doesn't make private methods completely impossible — Ruby does it with a similar message-passing system — but it does make them somewhat awkward.
Even Ruby's implementation of private methods is a bit confusing to people because of the strangeness (you can send the object any message you like, except for the ones on this list!). Essentially, Ruby makes it work by forbidding private methods to be called with an explicit receiver. In Objective-C it would require even more work since Objective-C doesn't have that option.
It's an issue with the runtime environment of Objective-C. While C/C++ compiles down into unreadable machine code, Objective-C still maintains some human-readable attributes like method names as strings. This gives Objective-C the ability to perform reflective features.
EDIT: Being a reflective language without strict private methods makes Objective-C more "pythonic" in that you trust other people that use your code rather than restrict what methods they can call. Using naming conventions like double underscores is meant to hide your code from a casual client coder, but won't stop coders needing to do more serious work.
There are two answers depending on the interpretation of the question.
The first is by hiding the method implementation from the interface. This is used, typically with a category with no name (e.g. @interface Foo()
). This permits the object to send those messages but not others - though one might still override accidentally (or otherwise).
The second answer, on the assumption that this is about performance and inlining, is made possible but as a local C function instead. If you wanted a ‘private foo(NSString *arg
)‘ method, you would do void MyClass_foo(MyClass *self, NSString *arg)
and call it as a C function like MyClass_foo(self,arg)
. The syntax is different, but it acts with the sane kind of performance characteristics of C++'s private methods.
Although this answers the question, I should point out that the no-name category is by far the more common Objective-C way of doing this.
Objective-C doesn't support private methods because it doesn't need them.
In C++, every method must be visible in the declaration of the class. You can't have methods that someone including the header file cannot see. So if you want methods that code outside your implementation shouldn't use, you have no choice, the compiler must give you some tool so you can tell it that the method must not be used, that is the "private" keyword.
In Objective-C, you can have methods that are not in the header file. So you achieve the same purpose very easily by not adding the method to the header file. There's no need for private methods. Objective-C also has the advantage that you don't need to recompile every user of a class because you changed private methods.
For instance variables, that you used to have to declare in the header file (not anymore), @private, @public and @protected are available.
A missing answer here is: because private methods are a bad idea from an evolvability point of view. It might seem a good idea to make a method private when writing it, but it is a form of early binding. The context might change, and a later user might want to use a different implementation. A bit provocative: "Agile developers don't use private methods"
In a way, just like Smalltalk, Objective-C is for grown-up programmers. We value knowing what the original developer assumed the interface should be, and take the responsibility to deal with the consequences if we need to change implementation. So yes, it is philosophy, not implementation.
참고URL : https://stackoverflow.com/questions/2158660/why-doesnt-objective-c-support-private-methods
'development' 카테고리의 다른 글
SQL Server에서 DECIMAL과 NUMERIC간에 차이가 있습니까? (0) | 2020.07.12 |
---|---|
자바 : Instanceof와 제네릭 (0) | 2020.07.12 |
컴파일러가 예측 가능한 추가 루프를 곱셈으로 최적화 할 수없는 이유는 무엇입니까? (0) | 2020.07.12 |
Android 키 저장소 파일이란 무엇이며 어떤 용도로 사용됩니까? (0) | 2020.07.12 |
왼쪽으로 만 첫 번째 행 (0) | 2020.07.12 |