ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OOP와 관련한 개념들(상속, 다형성, 동적바인딩...)
    JAVA 2011. 9. 12. 03:46
    추석맞이 포스팅 특집.
    무려 2개째. ㄷㄷㄷ


    OOP와 관련한 개념들을 한번 집고 넘어가고 싶었다.
    시작해보겠다.


    우리가 객체지향 언어를 사용하는 중요한 이유 중 하나는 기존에 구축되어 있는 시스템에 새로운 기능을 추가하거나 이미 존재하는 기능을 확장 하는 것이 다른 프로그램 언어보다 용이 하기 때문이다. 

    즉, 객체 지향 언어를 사용함으로써 유연성(Flexibility), 확장성(Extendability), 유지보수성(Maintenance)이 좋은 시스템을 다른 언어를 사용하는 것보다 쉽게 만들 수 있기 때문에 객체지향 프로그램을 사용하는 것이다.

    객체지향 언어의 특징은 상속(Inheritance), 캡슐화(Encapsulation), 정보은닉(Infomation hiding), 다형성(Polymorphism) 등으로 설명할 수 있다. 이러한 특징들 중에서도 특히 상속과 다형성이라는 개념은 객체지향의 가장 중요한 개념이다. 그 이유는 상속과 다형성을 통해 유연성과 확장성을 보장할 수 있기 때문이다.
     
    상속을 사용하면 부모 클래스의 모든 요소를 자식 클래스가 물려받을수 있다 . 이를 통해 부모 클래스의 데이터와 기능을 자식 클래스에서 재사용 할수 있게 되는데 사실 이런 재사용성 때문에 상속이 필요한 것은 아니다. 상속은 다형성을 구현하기 위한 전재조건으로서 중요한 의미를 갖는 것이지 소스의 재사용성은 큰 의미를 가지지 않는다 . 상속과 더불어 다형성을 구성하는 중요 요소는 Overriding(메소드 재정의)과 Dynamic Binding(동적 결합) 이 있다.

    OOP의 관점에서의 다형성을 한 문장으로 표현하면 다음과 같다.
    동일한 타입으로 묶을 수 있는 여러 객체에게 동일한 명령을 내렸을 때 각자 다른 동작을 하는 것을 의미한다. 

    소스를 보며 살펴보자.

    PublicTransportation.java
     

    Bus.java

    Taxi.java

     

    Test.java

    결과값

    자식클래스인 Bus 와 Taxi 에 공통으로 들어갈 변수와 메소드를 부모클래스인 PublicTransportation 으로 옮기고 자식 클래스에는 공통된 변수와 메소드를 상속받아 사용하도록 한다. PublicTransportation 클래스를 상속한 자식 클래스들은 getFare() 라는 추상메소드를 적절하게 Overriding 한다.

    대중교통 요금을 구하기 위해 작성한 simulation() 메소드를 보면 하나의 메소드로 두 개의 대중교통의 요금을 구하는 것을 알 수 있다. 그리고 simulation() 메소드가 그렇게 동작하게 할 수 있게 된 중요한 요인은 simulation() 메소드의 매개변수가 특정 객체 타입이 아닌 모든 대중교통을 받아들일 수 있는 PublicTransportation 으로 지정됐기 때문이다. 따라서 새로운 KTX 가 추가 된다 하더라도 simulation() 메소드를 새롭게 추가할 필요가 없게 된 것이다.

    다형성을 이용했기 때문에  simulation() 메소드는 PublicTransportation 계열의 자식 객체라면 어떤 대중교통이 됐던 모두 동작시킬수 있다. 결과적으로 기능의 추가로 인한 소스의 수정이 최소화되었다.

    이게 바로 다형성이다!


    앞에서 잠깐 Dynamic Binding 에 관해 언급했는데, 그것도 집고 넘어가겠다.
     
    자바에서는 동적바인딩을 한다.
    그렇기 때문에 자바에서 상속이나 다형성이 가능하다.

    바인딩이란?
    바인딩[binding]
    프로그래밍 용어로서, 각종 값들이 확정되어 더 이상 변경할 수 없는 구속(bind) 상태가 되는 것. 
    프로그램 내에서 변수, 배열, 라벨, 절차 등의 명칭, 즉 식별자(identifier)가 그 대상인 메모리 주소, 데이터형 또는 실제값으로 배정되는 것이 이에 해당되며, 
    원시 프로그램의 컴파일링 또는 링크 시에 확정되는 바인딩을 정적 바인딩(static binding)이라 하고, 
    프로그램의 실행되는 과정에서 바인딩되는 것을 동적 바인딩(dynamic binding)이라고 한다. 
    프로그램 작성에서는 바인딩을 가급적 뒤로 미루도록 권고하고 있다.  
    - daum 백과사전 中


    Dynamic Binding(Late Binding)에 반대대되는 개념이 Static Binding(Early Binding)이라 할 수 있다. 

    소스를 살펴보자,

    Car.java
     

    Sonata.java
     

    Test.java


    결과값


    위와 같은 간략한 클래스 3개가 있다.

    Test는 이 두가지 클래스를 사용하고 있는 간략한 코드를 표현한다.
    Car 는 부모 클래스이며, Sonata는 Car를 상속받는 클래스이고 Car 클래스의 getName() 메소드를 오버라이딩 하였다.

    Test 의 내용을 살펴보면 c과 s라는 이름의 Car 형의 객체가 두 개가 생성되어 있는 것을 볼 수 있다.
    하지만 실제로 c 는 Car의 인스턴스를 나타내고 있으며 s는 Sonata의 인스턴스를 나타내고 있다.

    그리고 세 번째 줄과 네 번 째 줄에서 같은 이름의  getName() 메소드를 호출하고 있다.
    getName() 메소드가 오버라이딩 되어있기 때문에 세 번째 줄과 네 번 째 줄의 
    getName가 어떤 클래스의  getName를 나타내는지는 컴파일시에 결정되지 않는다.

    getName() 메소드가 어떤 클래스의 메소드를 나타내는지는 런타임시간, 즉 Test 클래스 파일이 실행하는 시점에서 결정이 된다는 말이다.

    이것이 동적바인딩이라는 개념이다.
    자바에서 동적바인딩을 하는 것은 맞는 말이지만 모든 메소드에 대해 동적 바인딩을 하는 것은 아니다. 

    모든 인스턴스 메소드는 런타임시에 결정되지만 스태틱(static) 메소드는 컴파일 시에 결정이 된다. 인스턴스 변수 또한 컴파일시에 결정된다. 


    다음 소스를 보자.

    Car.java

     

    Sonata.java

     

    Test.java


    결과값

    앞에 소스와 비슷한데 차이점을 찾았는가?


    Car 클래스에 변수를 추가했고 메소드를 static으로 바꾸었으며
    Sonata 클래스는 그것들을 오버라이딩 하고있다. 

    이번 Test 클래스의 세 번 째 줄과 네 번 째 줄은 앞에 소스와는 달리 모두 Car 를 호출한다. 
    다섯 번 째 줄과 여섯 번 째 줄의 변수들도 모두 Car 의 인스턴스 변수를 나타낸다. 

    이렇게 되는 이유는 인스턴스 변수와 스태틱 메소드는 동적바인딩 되지 않기 때문이다.



    끝!! 


Designed by Tistory.