본문 바로가기

플밍 is 뭔들/JavaScript&jQuery

[JavaScript] 자바스크립트 객체지향 프로그래밍 - 다형성

※ 다형성이란?
다형성은 특정 기능을 선언(설계)부분과 구현(동작)부분으로 분리한 후 구현부분을 다양한 방법으로 만들어 
선택하여 사용할 수 있게 하는 기능이다.

몇가지의 예를 들어보자
도형은 여러가지의 모양을 가지고 있다. 만약 다양한 도형을 그리고 싶을 때 삼각형을 그릴때와 사각형을 그릴때, 원형을 그릴때의 방법은 달라야 할 것이다.  그렇다면 각각의 도형을 그리는 메서드들의 선언을 따로 해줘야 할까?
그건 아니다. 아래 그림과 같이 인터페이스나 추상클래스에 Draw()라는 메서드를 선언하여 놓고 해당 기능을 쓰는 Triangle클래스, Square클래스, Circle클래스에서 상속을 받아 해당 클래스에서 클래스에 맞게 기능을 구현해주면 된다는 말이다.


또 다른 예로 콘센트를 생각해보자 
콘센트가 선언부분(인터페이스, 추상클래스), 케이블이 구현부분(일반 클래스, 추상 클래스)이 될것이다.
220V에 구멍이 두개 있는 콘센트를 사용하려면 우리는 단지 구멍 두개있는 220V짜리의 케이블을 갖고 있는 가전제품을 사면된다.
즉 콘센트(인터페이스나 추상클래스에 선언한 리턴값,매개변수)에 맞는 케이블 모양을 가지고 있다면 그걸 사용하는 가전제품이 티비이던 핸드폰 충전기이던 상관없이 모두 작동된다는 것이다.


※ 자바스크립트에서의 다형성
일반 객체지향 언어에서는 데이터 타입이 있다. 그래서 변수를 선언할 때 데이터 타입을 명시해야 한다. 하지만 자바스크립트의 경우는 그냥 변수라는 것만 알 수 있게 var 변수명 과 같은 식으로 데이터 타입을 명시하지 않고 선언을 한다.
ex) 
//자바에서 변수선언 
String a = "a";
//자바스크립트에서 변수선언
var a = "a";

//자바에서 메서드
void test(String a){}
//자바스크립트에서 메서드
function test( a ) {}

**일반 객체지향언어의 경우 데이터 타입을 맞추지 않으면 에러가 난다. 
하지만 자바스크립트의 데이터 타입을 명시하고 변수 사용을 하지 않기 때문에 변수값에 어떤 데이터를 넣어도 에러가 나지 않는다.


그리고 일반 객체지향에서 다형성을 구현하려면 매개변수와 리턴값을 상속받는 메서드에 맞추어 구현하여야 한다. 그렇지 않으면 에러가 난다.
하지만 자바스크립트에서는 인터페이스, 추상 클래스 그리고 엄격한 데이터 타입 체크 등의 다형성과 관련된 문법은 지원되지 않는다. 그렇다면 자바스크립트에서의 다형성은 어떻게 구현해야 할까? 그냥 다형성이 지원한다고 생각하고 규칙에 맞춰 구현하는 방법밖에 없다. 즉 구현부에서 메서드를 작성할 때 선언부가 있다는 가정 하에 맞춰 구현해줘야 한다. 


※ 자바스크립트에서 다형성 적용하기 예제
아래는 다형성을 적용한 예제이다. 예제는 4개의 정렬관련 클래스 (AlignHorizontal, AlignVertical, AlignRandom, AlignGrid)를 SimpleGallery 클래스의 show() 메서드에서 각각의 클래스의 align이라는 메서드를 호출하였다.
각각의 클래스에서 메서드의 이름(align())과 매개변수($images)는 같지만 정렬법에 따라 기능을 개별적으로 구현하였다.
그리고 자바스크립트에서 클래스를 생성하는 3가지 방법을 모두 사용하여 호출하였다.
<script>
    $(document).ready(function() {
        // 이미지 찾기.
        var img1 = new SimpleGallery("#container1 img");
        // 버튼 클릭 이벤트 실행.
        $("#btnHorizontal").click(function() {
            img1.show(AlignHorizontal);
        });
        $("#btnVertical").click(function() {
            var alignVertical = new AlignVertical();
            img1.show(alignVertical);
        });
        $("#btnRandom").click(function() {
            var alignRandom = new AlignRandom();
            img1.show(alignRandom);
        });
        $("#btnGrid").click(function() {
            img1.show(AlignGrid);
        });
     });
    // 심플갤러리 클래스
    function SimpleGallery(selector){
        this.$images = null;
        this.init(selector);
    }
    // 요소 초기화
    SimpleGallery.prototype.init=function(selector){
        this.$images = $(selector);
    }
    SimpleGallery.prototype.show=function(alignClass){
        /* 다형성과 관련된부분 
           정렬기능을 하는 함수 align의 매개변수를 이미지들의 정보가 있는 jQuery객체로 하여
           각 클래스마다 적절한 정렬의 기능을 구현하였다.
           단지 인터페이스나 추상클래스가 자바스크립트에서는 지원하지 않기 때문에 있다는 가정하에 
  코드작성
           원래라면 인터페이스나 추상클래스가 있고 각각의 클래스들 ( AlignHorizontal, 
  AlignVertical, AlignRandom, AlignGrid)에 인터페이스나 추상클래스를 
  implements나 상속받아 align()메서드를 오버라이드해서 구현했을 것이다.
        //각 클래스의 align이란 메서드를 $images란 매개변수를 넣어 호출한다.
        alignClass.align(this.$images);
    }
            
    // 이미지 가로 정렬 클래스
    // 오브젝트 리터럴 방식으로 생성한 클래스
    var AlignHorizontal= {
        align : function($images){
            // 이미지 개수 구하기.
            var length = $images.length;
            // 이미지 배열하기.
            for (var i = 0; i < length; i++) {
                var x = i * 200;
                $images.eq(i).css({
                    left : x,
                    top : 0
                 });
            } // for end

        } // function end
    }
            
    // 이미지 세로 정렬 클래스   
    // 함수 방식으로 생성한 클래스 
    function AlignVertical(){
        this.align = function($images){
            // 이미지 개수 구하기.
            var length = $images.length;
            // 이미지 배열하기.
            for (var i = 0; i < length; i++) {
                var x = i * 200;
                $images.eq(i).css({
                    left : 0,
                    top : x
                });
            }
         }
     }
      
    // 이미지 랜덤 정렬 클래스   
    // 함수 방식으로 생성한 클래스       
    function AlignRandom(){}
    AlignRandom.prototype.align = function($images){
        // 이미지 개수 구하기.
        var length = $images.length;
        // 이미지 배열하기.
        for (var i = 0; i < length; i++) {
            var x = Math.floor(Math.random()* 1000);
            var y = Math.floor(Math.random()* 1000);
            $images.eq(i).css({
                left : x,
                top : y
            });
        }
     }
     
    // 이미지 바둑판식 정렬 클래스   
    // 오브젝트 리터럴 방식으로 생성한 클래스
    var AlignGrid = {
        align : function($images){
            // 이미지 개수 구하기.
            var length = $images.length;
            var y = 0;
            var x = 0;
            // 이미지 배열하기.
            for (var i = 0; i < length; i++) {
                $images.eq(i).css({
                    left : x,
                    top : y
                });
                x = x + 200;
                if((i+1)%3 == 0){
                    y = y + 200;
                    x = 0;
                }  // if end

            // for end

        // function end
    }
            
</script>