2016년 11월 8일 화요일

OOP 추상화(Abstraciton)

OOP의 특징 중 하나가 추상화(Abstraciton)입니다. 그런데 이 추상화가 뭘까요? 피카소의 그림일까요?

'추상화'란 것은, 어떤 기능을 가진 객체를 구현할때, 객체 외부에서는 그 기능의 정확한 묘사를 하지 않는 것입니다. 그 대신 그 기능의 '추상적 행위'를 묘사해야 합니다.

이를테면 다음과 같은 잠수함을 구현한다고 해 봅시다.

class Submarine
{
    private int x;    // x좌표
    private int y;    // y좌표
    private int depth;// 깊이

    public int GetX() { return x; }
    public int SetX(int x) { this.x = x; }
    ...........
}

void Function(Submarine ship)
{
    // 북쪽으로 이동
    ship.SetY(ship.GetY() - 1);


    // 수면으로 이동
    if(ship.GetDepth() > 0)
        ship.SetDepth(ship.GetDepth() - 1);
}

이런 식으로 해도 동작은 하겠죠. 하지만 이런 구현을 한다면 구태여 OOP 프로그램을 사용할 필요가 없습니다. 그냥 C로도 구현되는 수준이거든요. 오히려 C로 하면 저런 잡다한 멤버함수를 만들 필요도 없이 쉽게 끝납니다(하지만 그냥 C 프로그램에서도 이런 식의 프로그램은 좋지 않습니다*).

이것을 제대로 추상화를 구현한다면 이런 식이 되어야 합니다.

class Submarine
{
    private int x;    // x좌표
    private int y;    // y좌표
    private int depth;// 깊이

    public void ToEast() { ++x; }
    public void ToWest() { --x; }
    public void ToSouth() { ++y; }
    public void ToNorth() { --y; }

    public void Float()
    {
        if(depth > 0)
           --depth;
    }

    public void Sink() { ++depth; }
}

void Function(Submarine ship)
{
    // 북쪽으로 이동
    ship.ToNorth();

    // 수면으로 이동
    ship.Float();
}


이런 식으로 Submarine 밖에서는 Submarine의 멤버변수 자체를 생각하지 않고 코딩하는 것이 '추상화'입니다. x니 y니 따위를 생각하지 않고 오로지 '북쪽으로 이동'만 코딩하는 것이죠. '구체화'는 Submarine.ToNorth() 안에서 하고 말입니다.
캡슐화(Capsulation)는 멤버변수에 직접 접근이 힘들 뿐, 실제 멤버변수가 뭐가 있는지 알 수는 있다는 점에서, 추상화는 캡슐화보다 한단계 더 진행한 개념이라고 볼 수 있죠.

만약

class Ocean
{
    ......

    public bool IsReef(int x, int y)    // 암초가 있는가
    {
        .....
    }
}

class Submarine
{
    private int x;    // x좌표
    private int y;    // y좌표
    private int depth;// 깊이

    public int GetX() { return x; }
    public int SetX(int x) { this.x = x; }
    ...........
}

void Function(Ocean ocean, Submarine ship)
{
    // 북쪽으로 이동
    ship.SetY(ship.GetY() - 1);

    // 암초에 걸렸는지 체크
    if(ocean.IsReef(ship.GetX(), ship.GetY())
        ship.Destroyed();
}

이런 것은 '캡슐화'는 되었지만(x, y변수가 '캡슐화되었죠) '추상화'가 된 코드는 아닙니다. '추상화'를 시킨다면

class Ocean
{
    ......

    public bool IsReef(int x, int y)    // 암초가 있는가
    {
        .....
    }
}

class Submarine
{
    private int x;    // x좌표
    private int y;    // y좌표
    private int depth;// 깊이

    public void ToEast() { ++x; }
    public void ToWest() { --x; }
    public void ToSouth() { ++y; }
    public void ToNorth() { --y; }

    public bool IsSafe(Ocean ocean)
    {
        if(ocean.IsReef(x, y))  // 암초에 걸렸으면
            return false;
        // 다른 상황 체크

        // 모두 통과했으면 안전
        return true;
    }
    ...........
}

void Function(Ocean ocean, Submarine ship)
{
    // 북쪽으로 이동
    ship.ToNorth();

    // 배가 안전한지 체크
    if(ship.isSafe(ocean))
        ship.Destroyed();
}


가 되어야 합니다.


* 위에서 저런 식의 코딩은 C에서도 좋지 않다고 했는데, C에서의 코딩은 다음과 같이 하는 것이 좋습니다.

struct Ocean
{
    ......
}

struct Submarine
{
    int x;    // x좌표
    int y;    // y좌표
    int depth;// 깊이
}

void ToEast(Submarine ship) { ++ship.x; }
void ToWest(Submarine ship) { --ship.x; }
void ToSouth(Submarine ship) { ++ship.y; }
void ToNorth(Submarine ship) { --ship.y; }

bool IsSafe(Ocean ocean, Submarine ship)
{
    if(ocean.IsReef(ship.x, ship.y))  // 암초에 걸렸으면
        return false;
    // 다른 상황 체크

    // 모두 통과했으면 안전
    return true;
}

void Function(Ocean ocean, Submarine ship)
{
    // 북쪽으로 이동
    ToNorth(ship);

    // 배가 안전한지 체크
    if(isSafe(ocean, ship))
        Destroyed(ship);
}

댓글 없음:

댓글 쓰기