* 확장 함수란?
기존에 정의된 클래스에 함수를 추가하는 기능.
직접 만든 클래스가 아닌 다른 사람이 만든 클래스에는 함수를 추가하기 어렵기 때문에 확장 함수 사용.
어떤 클래스의 멤버 메소드인 것처럼 호출할 수 있지만, 실제로는 그 클래스의 밖에 선언된 함수
* 확장 함수 생성 방법

* 확장 함수 예시 (String)


-> String 클래스 내부를 직접 수정하지 않고, String 클래스에 lastChar라는 새로운 함수를 생성.
- receiver type (수취인 타입) : 확장 함수를 추가할 클래스. 확장 대상이 될 클래스 ex) String
- receiver object (수취인 객체) : receiver type이 가지고 있는 인스턴스 ex) this -> "kotlin"문구
* 특징
- 확장함수는 정적바인딩 된다.
- 이미 클래스 내부에 존재하는 클래스와 이름, 매개변수 타입, 매개변수 개수가 완벽하게 같은 함수는 무시된다.
(이런 경우는 확장함수 호출 시 확장함수의 내용을 호출하는 것이 아닌 멤버함수의 내용이 호출된다.)
- 확장함수는 멤버변수를 오버로딩 할 수 있다.
(이름은 같고 매개변수의 타입이나 개수가 다르면 확장함수와 멤버함수 구분이 가능하다.)
- 확장함수는 오버라이드 할 수 없다.
- 보일러 플레이트 코드를 줄일 수 있다.
- 확장 함수를 정의했어도 모든 곳에서 사용할 수는 없다. (import 했을 경우 사용 가능하다.)
* 정적 바인딩 vs 동적 바인딩
- 정적 바인딩 : 함수 호출 부분에 메모리 주소 값을 저장하는 작업이 컴파일 시간에 행해진다.
= 컴파일 이후로 값이 변경되지 않는다.
- 동적 바인딩 : 함수 호출 부분에 메모리 주소 값을 저장하는 작업이 컴파일 시간에 보류되다가 런타임에 행해진다.
= 실행 시점에 객체 타입에 따라 동적으로 호출될 대상 메소드를 결정한다.
* 상속 관계의 클래스에서 확장함수를 오버라이드 할 때

- 일반 멤버 함수는 오버라이드 가능
-> 런타임 시간에 함수의 메모리 주소가 결정된다.
-> click() 호출 시 ButtonClass 클래스의 함수가 실행된다.
-> ButtonClass()라는 객체를 따라간다.
= 동적 바인딩
- 확장 함수는 오버라이드 불가능
-> 컴파일 시간에 ViewClass의 메모리 주소로 결정된다.
-> showOff() 호출 시 ViewClass 클래스의 함수가 실행된다.
-> ViewClass라는 타입을 따라감
= 정적 바인딩