안녕하세요. 이번 시간에는 자바스크립트에서 오버라이딩(overriding)과 오버로딩(overloading)의 차이에 대해 알아보겠습니다! 자바스크립트 강좌를 안 쓰려고 했는데 자꾸 쓰게 되네요. 자바스크립트의 마력이랄까요. ㅎㅎ
자바를 배우신 분들은 오버라이딩과 오버로딩에 대해 잘 아실테지만 자바스크립트로 프로그래밍을 시작하신 분들은 용어가 다소 생소할 수 있겠네요. 심지어 용어가 비슷하기도 해서 헷갈리기도 합니다.
오버로딩
스타크래프트의 오버로드와는 아무 상관도 없습니다. (철자가 다릅니다 ㅎㅎ) 자바스크립트에는 사실 없는 개념입니다. 자바스크립트는 함수의 매개변수가 자유롭기 때문입니다. 하지만 다른 언어에서는 매개변수의 개수 또는 자료형에 따라서 함수를 다르게 선언하는 경우가 있습니다. 아래는 자바의 경우입니다.
void overload(){
System.out.println("매개변수 0개");
}
void overload(int i, int j){
System.out.println("매개변수 "+ i + " 그리고 " + j);
}
void overload(double d){
System.out.println("매개변수 " + d);
}
자바스크립트에서는 위와 같이 하면 제일 아래에 선언한 함수가 같은 이름의 함수를 덮어씌워버립니다. 따라서 자바스크립트는 하나의 함수로 여러 개의 매개변수 또는 다양한 자료형의 매개변수를 처리하는 기법이 필요합니다.
여러 라이브러리들이 이렇게 가변적인 매개변수를 받습니다. 제이쿼리의 경우 $ 함수는 다재다능합니다. $(function() {})
처럼 함수를 받으면 이벤트 리스너를, $(document)
를 하면 DOM을, $('#zero')
를 하면 선택자를 처리합니다. 제이쿼리의 on함수도 on('click', function() {})
이면 이벤트 리스너를, on('click', '#zero', function() {})
이면 이벤트 델리게이션을 처리합니다. 자료형이 다를 때도 있고, 매개변수 개수가 다를 때도 있습니다.
예를 들어 매개변수로 문자열 두 개와 콜백, 또는 옵션 객체 하나와 콜백, 또는 그냥 콜백 한 개만 가지는 함수를 생각해봅시다. 콜백은 문자열이나 옵션이 뭔지 console.log를 찍어주는 함수라고 칩시다. 이처럼 하나의 함수가 세 가지 경우를 모두 처리해야 합니다. 한 번에 만들기 어렵다면 나눠서 생각하면 됩니다.
function overload(a, b, c) {}
위와 같은 함수를 먼저 만들고, 각각의 경우를 생각해봅시다. 문자열 두 개와 콜백을 가지는 경우는 a,b가 문자열, c가 콜백일 것입니다. 옵션 객체와 콜백을 가지는 경우는 a가 옵션 객체, b가 콜백일 것이고요. 그냥 콜백만 가지면 a가 콜백일 것입니다. 이것을 분기 처리하면 됩니다.
function overload(a, b, c) {
if (typeof c === 'function') { // 문자열 두 개와 콜백
c(a, b);
} else if (typeof b === 'function') { // 옵션 객체와 콜백
b(a);
} else { // 콜백 하나
a();
}
}
위와 같이 하면 됩니다. 각각의 경우를 모두 대응하고 있습니다. 자바가 더 보기 좋을 수도 있습니다. 하지만 우리는 자바가 아닌 자바스크립트를 하고 있기 때문에 어쩔 수 없습니다.
function callback(a, b) {
if (b) {
console.log('문자열', a, b);
} else if (a) {
console.log('옵션 객체', a);
} else {
console.log('매개변수 없음');
}
}
overload('zero', 'babo', callback); // 문자열 zero babo
overload({ name: 'zero', value: 'babo' }, callback); // 옵션 객체 { name: 'zero', value: 'babo' }
overload(callback); // 매개변수 없음
정상적으로 실행됩니다. 재밌는 점은 callback도 오버로딩과 비슷한 동작을 하고 있다는 것입니다. 저는 자바스크립트의 자유도가 참 좋습니다.
오버라이딩
자바스크립트 객체의 상속받은 부모의 메소드를 재정의하는 것을 의미합니다. 오버라이딩이라는 개념은 존재하지만 자바같은 언어와는 또 다릅니다. 매개변수가 자유롭고, 리턴값의 자료형도 자유롭습니다. ES5 코드로 설명하겠습니다.
var Animal = function() {
};
Animal.prototype.move = function() {
console.log('동물이 움직여요');
};
var Cat = function() {
Animal.apply(this, arguments); // 속성 상속받는 방법
}
Cat.prototype = Object.create(Animal.prototype); // 프로토타입 상속 방법
Cat.prototype.constructor = Cat; // 버그 패치
console.log(new Animal().move()); // 동물이 움직여요
console.log(new Cat().move()); // 동물이 움직여요
Cat.prototype.move = function(sound) { // 오버라이딩
console.log(sound + ' 움직여요');
return '야옹';
};
console.log(new Cat().move('살금살금')); // 살금살금 움직여요
위의 코드는 자바스크립트에서 객체를 상속하는 코드입니다. 고양이가 동물을 상속하고 있습니다. 상속 방법은 알아두시면 좋습니다. 관련 강좌 는 여기에 있습니다.
Animal과 Cat 모두 move라는 메소드를 가지고 있습니다. Cat에 move를 추가하기 전에는 Cat은 Animal의 move를 상속받아 사용했습니다. 그런데 Cat이 다시 move를 재정의하니까 Animal의 move 대신 Cat의 move가 호출됩니다. 즉 부모 객체의 메소드를 덮어씌운 것입니다. 게다가 매개변수도 하나 받고 리턴 값도 생겼습니다.
자바와는 달리 부모 메소드를 오버라이딩할 때 매개변수와 리턴 자료형이 달라도 됩니다. 이는 잘 생각해보면 당연합니다. 자바스크립트에 오버로딩이란 개념이 없기 때문입니다.
다른 언어에서는 위와 같이 비유하기도 합니다. 하지만 자바스크립트에서는 위 그림이 적용되지 않는다는 것 알아두시면 되겠습니다.
오늘도 간단하게 오버로딩과 오버라이딩의 개념을 알아보았습니다. 물론 배우고 나서도 계속 이름은 헷갈리지만, 이런 두 개가 있다는 것을 알고 계시면 좋겠습니다!
Cat.prototype.constructor = Cat; // 버그 패치
버그 패치란게?? 무슨 버그가 있는건가요??
Cat.prototype 이 Animal.prototype 로 바껴서..
prototype 의 생성자 부분만 Cat으로 변경하는 건가요??