본문 바로가기

자바스크립트

03. 자바스크립트 OOP구현과 상속에 대해...


Javascript OOP구현과 상속에 대해...




1. 개요



오랫동안 UI를 개발해 오면서 자주 사용해 오던 개발방법 중 하나가 객체지향방법(Object-Orientied Programming )이다. OOP에서 중요한 몇가지 개념만 알아보자.


    1. 클래스 - '객체( 인스턴스 )를 정의해 놓은 원형이 되는 것'
    2. 객체 - new 클래스를 이용해서 생성된 자료형 변수 또는 '인스턴스'라고도 한다.
    3. 은익성 - 객체 또는 클래스 속성 중 외부 접근을 허용하는 것 이외의 모든 것들은 접근을 막는다.
    4. 상속 - 이미 만들어진 기능을 파생시켜 하위 클래스를 만든다.
    5. 오버라이딩 - 상위 클래스의 메서드를 하위클래스에서 기능만 바꿔 동일하게 선언해서( 덮어써서 ) 사용한다.
    6. 다형성 - 여러개의 객체 내에 동일한 메서드가 있지만 모두 다른 기능을 제공한다.


2. 구현방법 및 설명



첫번째, 클래스 정의 및 생성


자바스크립트에서는 클래스 함수가 따로 존재하지 않고, 함수선언식 또는 함수표기식으로 사용한다.함수를 클래스로 쓰고자 한다면 선언명의 첫글자는 대문자로 쓰길 권장하고 있다.


// 함수선언식

function MyClass() {}


// 함수표기식

var MyClass = function() {};



두번째, 은익성 구현


설명: 클래스 기반 언어에서는 일반적으로 은익성을 보장하는 'private' 이라는 예약어를 제공한다. 하지만 자바스크립트에서는 따로 제공하지 않기 때문에 다른 방법으로 구현해야 한다.


// 은익성 보장이 안됨

var Person = function() {

this.sex = "여성";

this.age = 30;

};


var woman = new Person();

console.log( woman.age );   // 출력 - "30"


// 은익성 보장 : 여성의 나이를 숨기고 싶다.

var Person = function() {

var age = 30;

this.sex = "female";

};


var woman = new Person();


// 객체 내 var 예약어를 이용해 외부 접근 차단( 은익성 보장 )

console.log( woman.age );   // 출력 - "undefined"


// 객체 내 속성은 접근이 가능

console.log( woman.sex );     // 출력 - "female"


// 은익성이 보장된 속성에 접근을 허용하려면 메서드를 제공하라.

var Person = function() {

var age = 30;

this.sex = "여성";


this.getAge = function() {

return age;

};

};


var woman = new Person();

console.log( woman.getAge() );   // 출력 - "30"



세번째, 상속


설명: 자바스크립트에서는 상속 키워드가 따로 존재하지 않지만, 

  prototype 예약어를 이용해서 비슷한 기능 구현이 가능하다.


// 먼저 상속할 상위 클래스 정의 

var SuperClass = function() {

var age = 60;

var sex = "female";


this.getSex = function() {

return sex;

};


this.getAge = function() {

return age;

};

};


// 상위클래스( SuperClass )를 상속받을 하위클래스 정의

var SubClass = function() {

var name = "Julia";


this.getName = function() {

return name;

};

};


SubClass.prototype = new SuperClass();


var person = new SubClass();


// 서브클래서에서 상위클래스에 있는 메서드 호출이 가능하다.

console.log( person.getSex() );        // 출력 - "female"


// 서브클래스 내 메서드도 그대로 호출이 가능하다.

console.log( person.getName() );     // 출력 - "Julia"



네번째, 오버라이드( override )


설명: 상위클래스에 구현된 메서드를 하위클래스에서도 동일한 이름의 메서드를 구현할 때

  이러한 행위를 "override" 라고 한다. 오버라이드는 다형성과 밀접한 관계를 갖는다.


var SuperClass = function() {

var name = "engine";


this.run = function() {

console.log("움직인다.");

};

};


var Car = function() {

var name = "car";


this.run = function() {

console.log("굴러간다.");

};

};

Car.prototype = new SuperClass();


var Airplane = function() {

var name = "airplane";


this.run = function() {

console.log("날라간다.");

};

};

Airplane.prototype = new SuperClass();


// 아래 예시 결과를 보면 SuperClass에 있는 "run"메서드의 내용은 출력되지 않음을 알 수 있다.

var car = new Car();

car.run();     // 출력 - "굴러간다."


var airplane = new Airplane();

airplane.run();     // 출력 - "날라간다."



다섯번째, 다형성 


설명: 다형성이란 동일한 메서드의 호출로 객체에 따라 다양한 동작을 할 수 있게 정의하는 방법이다.

  하나의 인터페이스로 성격이 같은 객체들을 제어할 수 있으므로 코드의 일관성이 유지된다.


// 자바스크립트에서 인터페이스에 대해 사례가 있는지 한번 찾아봐야 겠다.

var IMovealbe = function() {

this.run = function() {

// 이 인터페이스를 상속받은 자식객체는 재구현(override)해서 사용하기로 약속하자.

};

};


var Car = function() {


// 약속을 지켰음

this.run = function() {

console.log("굴러간다.");

};

};

Car.prototype = new IMovealbe();


var Airplane = function() {


// 약속을 지켰음

this.run = function() {

console.log("날아간다.");

};

};

Airplane.prototype = new IMovealbe();


var Ship = function() {


// 약속을 어겼음

this.wave = function() {

console.log("파도를 가르면 간다.");

};

};

Ship.prototype = new IMovealbe();


var car = new Car();

car.run();     // 출력 - "굴러간다."


var airplane = new Airplane();

airplane.run();     // 출력 - "날아간다."


var ship = new Ship();

ship.wave();     // 출력 - "파도를 가르며 간다."


// 장치제어 관리자 생성 

var machineMannager = [];


machineMannager.push(car);

machineMannager.push(airplane);

machineMannager.push(ship);


for (var i=0; i<machineMannager.length; i++) {

machineMannager[i].run();

}


위 for문은 배열 3번째에서 약속을 어겼기 때문에( 자바스크립트에 규정은 없음 ) 에러가 발생할 것이다.

위 에러 문제를 해결할 수 있는 방법은 두가지가 있다.


첫번째 방법은 wave 메서드를 run으로 바꿔주면 간단히 끝난다.

하지만 그렇지 못한 경우도 있을 것이다.

이때 사용할 수 있는 두번째 방법은 'Adapter패턴'( 'Wrapper패턴'이라고도 함 )을 이용해서 

wave함수를 run함수로 한번 더 감싸서 해결할 수 있다.


var AdapterShip = function() {

// Wrapper함수를 사용한다.

this.run = function() {

this.wave();

};

};

AdapterShip.prototype = new Ship();


var newShip = new AdapterShip();

newShip.run();     // 출력 - "파도를 가르며 간다."


위 장치제어관리자 부분에서

machineMannager.push(ship);

이 부분을 

machineMannager.push(newShip);

으로 수정해서 다시 테스트해 보면 3번째 출력이 안됐던 Ship 부분 정상적으로 출력 될 것이다.