어떤 경우에는 느리거나 효율성을 따져볼수 있는지... 고민을 해봐야한다
깊은 부분을 이해하면 컴퓨터가 어떤 방식으로 메서드들이 동작을 하는지.. 좋은 개발자가 되기위해 기본적인 지식을 쌓는 과정이라고 생각하자
즉.. 큰 그림을 알고있자
코드 데이터 힙 스택 영역이 있다
실제로 이 메서드는 Cpu에 대한 명령어다
해당 코드들은 코드영역에만 존재한다
코드영역에 저장되어있는 함수, 메서드를 실행시키려면 메서드 주소가 필요
어떤 클래스에 메서드를 실행시킬때 어떤 메서드를 실행시키는지.. 이러한 관련내용을 기록해보자
함수, 메서드를 실행시키는 방법은 크게 3가지로 나뉜다
컴파일 타임에 일어난다
작성한 코드는 기계어로 해석을 한다 (컴파일 타임)
그때 어떤 메모리에 메모리 주소를 인식한다
함수 메모리 주소를 삽입하거나 함수의 명령 코드를 해당위치에 삽입한다
코드영역의 명령어가 있고 이것을 박스로 묶은거처럼 상상하면 이것이 함수나 메서드라고 생각하자
명령어가 시작되는 부분에 90번 메모리 주소의 함수가 들어있다
해당 함수를 실행 시키려면 90번 이라는 메모리 주소를 기억하고 있어야한다
더 빠르게 실행하려면 ?
90번째 메모리에 있는 함수 명령어 묶음을 해당 줄에 넣어버린다
긴 함수가 아니면 명령어를 복사해서 붙히면 이 과정에서 메모리가 많이 들지 않는다
명령 코드를 해당위치에 코드를 심어 버리는것(in-line)
구조체나 열거형의 메서드가 이런식으로 실행이 된다
상속이나 다형성의 구조가 없을때 사용된다
런타임에 발생된다
실제로 앱이 실행되고 있는 동안에 메모리 주소를 찾아 실행시키는 구조
Message Dispatch는 예전 objective-c에서 쓰이던 방식이다
참고하자
Table Dispatch는 클래스와 관련된 메서드 테이블들은 버츄얼 테이블이 있다
클래스 테이블 : Virtual Table
클래스 테이블 안에선 메서드의 이름과 주소가 저장되어 있다
배열 형태로 저장된다
자식 클래스에서도 따로 메서드의 배열로 저장이된다
Message Dispatch는
메서드1을 그대로 가져와 자식 클래스의 테이블에 그대로 가져오는것이 아닌 예시로 부모 클래스에서 메서드를 재정의 하면 따로 자식 클래스의 테이블에서 생성을 한다
재정의 하지 않은 메서드라면?
자식 클래스의 테이블에서 기억을 하지 않고 super클래스를 찾아간다
자식 클래스의 테이블에서 재정의하지 않은 메서드를 실행시키면 해당 테이블에 없으니 다시한번 부모 클래스를 찾아가 재정의 하지 않은 메서드를 찾아서 실행을 시킨다
자식 클래스 테이블에서 테이블을 찾고 없으면 다시 부모클래스를 찾아가 해당 메서드들을 찾아야 하므로 속도가 느리다
Table Dispatch를 두가지로 나누면
클래스에서 사용하는 Virtual Table을 사용하고
프로토콜을 채택을 해서 구현하면 추가적으로 Witness Table을 만든다
프로토콜을 채택했을때 어떤 메서드를 실행시킬지 보는 테이블이다
함수의 메모리 주소를 포인터 라고한다
각 테이블에 이 포인터가 저장이되서 코등영역에 찾아가 메서드를 실행 시킨다
구조체나 열거형은 벨류타입이고 메서드를 구현하면 상속개념이 없기 때문에
Direct Dispatch방식으로 동작을 한다
프로토콜 같은경우 본체에서 요구사항으로 요구하는 메서드를 구현하면
Witness Table을 만듬
프로토콜 확장에서 요구사항으로 선언되어 있지 않은 메서드는 Direct Dispatch로 동작
본체의 요구사항 메서드를 Witness Table로 구현
프로토콜을 채택한 타입마다 테이블을 만듬
단, @objc dynamic키워드를 이용해 Message Dispatch방식으로 변경시 확장(extension안에 메서드 재정의가 가능)
@@ 클래스를 상속을 하지 않기하기 위해서는 final 키워드를 정의한다
이럴때는 Direct Dispatch로 동작 해당 자리에다가 함수의 포인터를 삽입한다
해당 프로토콜 채택시
Witness Table을 생성 그 안에 메서드들이 있다
채택한 클래스에서 버츄얼 테이블 안에 메서드들은 두개 다 완전히 동일하다
채택하면 프로토콜 테이블에서 버츄얼 테이블이 해당 메서드를 가져온다 (동일한 메서드 주소가 들어있다)
_해당 인스턴스에서
class형식으로 저장이 되어있을때 class참조
프로토콜 형식으로 저장이 되어있을때 프로토콜 타입 참조__**