ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [객체지향의 원리와 이해] (3-2) 자바와 객체지향 - 추상화:모델링
    개발/OOP, Design Pattern 2020. 12. 27. 14:27

    추상화 : 모델링

    추상 : [심리] 여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용
    피카소같은 화가의 작품을 보면 실제 사람과 비슷한 모습을 하지 않고 어떠한 특징들만을 표현하고 있다. 계급을 사람의 키로 표현한다던가 하는 방식으로 말이다.

    사전적 정의처럼 추상화 한다는 것은 어떠한 것을 표현할 수 있는 공통된 특징과 속성을 파악하여 표현하는 것을 말한다.

    추상화는 모델링이다

    객체지향의 4대 특성(캡,상,추,다)는 클래스를 통해 구현된다.
    클래스를 통해 '사람'을 구현한다고 했을 때, 먼저 클래스 설계를 한다. 설계를 하기 위해 사람의 공통된 특성을 뽑아보자.

    -   사람
        -   시력
        -   몸무게
        -   나이
        -   직업
        -   연봉
    
        -   먹다()
        -   마시다()
        -   눕다()
        -   자다()
        -   입금하다()
        -   출금하다()
        -   ....

    사람의 모든 특성을 나열하려면 끝없이 많기 때문에 경계가 필요하다.

    그 경계를 '애플리케이션 경계'이고 다른 말로 컨텍스트(Context)라고 한다. 이 경계를 알고싶다면 내가 창조하려는 세상은 어떤 세상인가?를 생각하면 된다.
    또는 프로그래밍적으로 내가 만들고자 하는 애플리케이션이 어디에 사용되는가?를 생각해보면 된다.

     

    만약 은행 애플리케이션이라면 사람의 특성중 어느 특성이 불필요한지 보이기 시작한다. 다음을 문장을 기억하고 불필요한 특성을 걸러보자.
    추상화란? 구체적인 것을분해해서 관심영역(애플리케이션 경계ㅡ Application Boundary)에 있는 특성만 가지고 재조합하는 것
    <=> 모델링

     

    모델은 실제 사물을 정확하게 복제하는게 아니라 목적에 맞게 관심있는 특성만을 추출해서 표현하는 것
    모델은 추상화를 통해 실제 사물을 단순하게 묘사하는 것

    -   사람
        -   나이
        -   직업
        -   연봉
    
        -   입금하다()
        -   출금하다()
        -   ....

    자바는 객체지향의 추상화를 class 키워드를 통해 지원하고 있다.
    클래스와 객체관계는 클래스 객체참조변수 = new 클래스(); 로 표현한다. (새로운 객체 하나를 생성해 그 주소를 참조변수에 할당)

     

    추상화와 T메모리

    위에서 학습한 내용으로 '쥐 캐릭터를 관리하는 애플리케이션'을 생각해보자. 먼저 쥐 캐릭터들의 특성을 생각한다.

    객체명 미키마우스 제리
    속성들 성명: 미키마우스
    국적: 미국
    나이: 87
    종교: 무교
    신장: 70cm
    체중: 11.5kg
    애완동물: 플루토
    여자친구: 미니마우스
    꼬리: 1개
    등등
    성명: 제리
    국적: 미국
    나이: 75
    종교: 기독교
    친구: 톰
    여자친구: null
    꼬리: 1개
    등등

    이 특성들을 이용해 모델링을 해야한다. 모델링에서 중요한 것은 추상화이고, 추상화는 관심있는 영역의 공통된 특성들을 뽑아내는 것이다. 추상화의 결과는 모델이다.


    그 특성들을 뽑아내 논리적 설계를 한다.

    -   쥐
        -   이름
        -   나이
        -   꼬리 개수
    
        -   울다()

     

    다음은 UML 다이어그램으로 한 물리적 설계이다.

     

    이제 모델을 클래스로 바꾸면 다음 코드가 나온다. (sing()메소드의 구현은 UML에 없다가 추가됌)

    public class Mouse {
        public String name;
        public int age;
        public int countOfTail;
    
        public void sing() {
            System.out.println(name + " 찍찍");
        }
    }

     

    그리고 이 클래스를 사용할 클래스도 작성한다.

    public class MouseDriver {
        public static void main(String[] args) {
            Mouse mickey = new Mouse();
    
            mickey.name = "mickey";
            mickey.age = 1;
            mickey.countOfTail = 1;
    
            mickey.sing();
            mickey = null;
        }
    }
    

     

    이제 이 코드를 실행했을 때 메모리를 보자.

    스택과 힙에는 아무것도 없고, 오로지 클래스영역(스태틱영역)에만 클래스 정보와 패키지가 로드되어 있다.

     

     

    main()메소드에 막 진입했을 때, 스택 영역에 main() 스택프레임이 생성되고 필요한 변수들의 영역을 할당한다.

     

     

    Mouse mickey = new Mouse(); 가 실행되었을 때 먼저 힙 영역에 객체를 생성한다.

     

     

    이후에 main() 스택프레임에 있는 mickey가 새로 생성된 객체의 주소를 할당받음으로써 해당 라인의 실행이 끝난다.

    (위 그림에는 안써있지만, 아래 그림처럼 :Mouse는 100번지에 위치한다 가정하고 mickey는 100번지를 가리키고 있다.)

     

     

    mickey.name = "mickey";
    mickey.age = 1;
    mickey.countOfTail = 1;

    코드가 실행됨에 따라 mickey 객체 참조변수가 가진 필드의 값들이 변경된다.

     

     

    mickey = null;가 실행된 후다. mickey 객체 참조변수는 더이상 아무것도 참조하지 않고, 참조되고 있던 객체는 더이상 참조되지 않아 Garbage Collector에 의해 쓰레기로 간주되어 수거된다.

     

     

    클래스 멤버 vs 객체 멤버 = static 멤버 vs 인스턴스 멤버

    클래스의 객체의 꼬리 개수는 모두 1개이다. 이 경우 어차피 countOfTail = 1인데 생성하는 모든 객체에서 일일이 코드를 작성해주고 메모리를 잡아먹는다. 이런 경우 값을 클래스에 저장할 수 있다. static 키워드를 사용하여 클래스 멤버 속성으로 만들어준다.

    public class Mouse {
        ...
        public static int countOfTail = 1;
        ...
    }

    이렇게 하면 항상 static 영역에 상주하여 static(정적) 멤버라고도 부르고, 스태틱 영역에 로드된 Mouse는 아래 그림처럼 클래스 내부에 countOfTail의 메모리 공간을 따로 확보한다. 그 외에 객체 속성은 속성명만 있고 실제 메모리 공간은 확보하지 않는다. (객체가 생성됬을 때 실제 메모리 공간을 할당한다.)

    클래스 멤버 = static 멤버 = 정적 멤버
    객체 멤버 = 인스턴스 멤버 = 오브젝트 멤버
    필드 = 속성 = 프로퍼티
    함수 = 메소드

     

     

    쥐 예제처럼, 정적 멤버 속성은 해당 클래스의 모든 객체가 공통된 값을 가질 때 사용한다.

    • 자동차 클래스의 바퀴 개수
    • 보병 클래스의 주특기 번호
    • 사람 클래스의 눈코입 개수
    • 등등

    main() 메서드는 당연히 정적 메소드여야 한다. T 메모리가 초기화된 순간 객체는 하나도 존재하지 않기 때문에 객체 멤버 메서드를 바로 실행할 수 없다.
    실무에서는 유틸리티성 메소드를 정적으로 만들어서 인스턴스를 만들지 않고 사용한다고 한다. (Math클래스 처럼)

     

     

    지역 변수는 별도로 초기화 하는데, 멤버 변수(속성)은 자동으로 초기화해주는 이유?

    클래스 속성과 객체 속성은 직접 초기화하지 않아도 정수형은 0, 부동소수점형은 0.0, 논리형은 false, 객체는 null로 초기화된다.
    지역변수는 한 지역에서만 사용되기 때문에 해당 지역에서 초기화할 책임이 있다. 그러나 클래스 속성과 객체 속성은 어디서든 접근가능한 공유변수의 성격이기 때문에 어디서 초기화해야 할지 명확하게 할 수 없다.

    댓글

Designed by Tistory.