본문 바로가기
Spring

객체 지향 프로그래밍의 4대 특성 (캡! 상추다)

by Jammini 2023. 6. 28.
728x90

목차

  1. 개요
  1. 클래스 vs 객체
  1. 객체 지향 프로그래밍이란?
  1. 객체 지향 프로그래밍의 장점
  1. 객체 지향의 4대 특성

    5-1. 캡슐화

    5-2. 상속

    5-3. 추상화

    5-4. 다형성

  1. 결론

1. 개요

  • 객체 지향의 4대 특성으로 좋은 상추가 떠오를 것이다. 흔히 앞글자를 따서 ‘캡! 상추다’ 같이 재밌는 표현을 사용한다.
  • 앞서, 간단하게 클래스와 객체를 알아보고 객체지향프로그래밍의 4대특성인 캡슐화, 상속, 추상화, 다형성에 대해 아래 내용을 차근차근 살펴보자.

2. 클래스 vs 객체

  • 세상에 존재하는 모든 것은 사물, 즉 객체(Object)다.
  • 각각의 사물은 고유하다.
  • 사물은 속성을 갖는다. ex) 사람의 키, 사람의 몸무게, 자동차의 속도 등
  • 사물은 행위를 한다. (무생물은 의인화 필요)
  • 객체를 인지할 때 우리는 분류(Class) 한다.
    • ex) 직립 보행하고 말을 하는 존재들을 ‘사람’이라고 분류한다.

‘객체’는 세상에 존재하는 유일무이한 사물(개체)

‘클래스’는 같은 속성과 기능을 가진 객체를 총칭하는 개념(분류, 집합)

# 클래스와 객체를 구분하는 방법

객체를 생성할 때는 아래와 같이 선언하여 사용된다.

클래스명 객체명 = new 클래스명();

객체와 클래스를 구분하고 싶다면 나이(제조년월)을 물어보면 된다.

  • 사람의 나이는 몇 살인가? → 클래스
  • 김연아의 나이는 몇 살인가? → 객체 (1990년생으로 2023년 기준 34살이다)
  • 뽀로로의 나이는 몇 살인가? → 객체 (2003년생으로 2023년 기준 21살이다)
  • 펭귄의 나이는 몇 살인가? → 클래스

즉, 클래스는 ‘분류’에 대한 개념일 뿐 실체에 해당하는 건 ‘객체’이다.

3. 객체 지향 프로그래밍이란?

  • OOP(Object-Oriented Programming)
  • 컴퓨터 프로그램을 어떤 데이터를 입력 받아 순서대로 처리하고 결과를 도출하는 명령어들의 목록으로 보는 시각에서 벗어나 여러 독립적인 부품들의 조합
  • 즉, 객체들의 유기적인 협력과 결합으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임을 의미한다.
  • 말 자체를 너무 어렵게 정의 된 것 같아 예를 들자면, 자동차를 만들때 수 많은 부품들의 결합과 연결로 하나의 완전한 자동차가 만들어지는 것과 같다고 보면된다. 즉, 객체를(작은부품) 먼저 만들고 객체들을 조립패서 하나의 완성된 프로그램을 뜻한다.

4. 객체 지향 프로그래밍의 장점

  • 객체 지향 설계를 통해 프로그램을 보다 유연하고 변경이 용이하게 만들 수 있는 점.
  • 컴퓨터 부품을 갈아 끼울때, 해당하는 부품만 갈아끼우고 다른 부품은 건드리지 않아도 되는 것처럼 각자의 독립적인 역할을 가지기에 코드의 변경을 최소화하고 유지보수하는데 유리하다.
  • 코드의 재사용을 통해 반복적인 코드를 최소화하고, 코드를 최대한 간결하게 표현 할 수 있다.
  • 우리가 경험하는 세계를 최대한 프로그램 설계에 반영하기 위해 노력하고 발전하기에 보다 인간 친화적이고 직관적인 코드를 작성하기에 용이하다.

5. 객체 지향의 4대 특성

이러한 객체 지향적 설계의 이점들을 가장 잘 살릴 수 있는 방향으로 4가지 특성인 캡! 상추다(캡슐화, 상속, 추상화, 다형성)가 있으며 아래에서 자세히 살펴보자.

1. 캡슐화 (정보은닉)

서로 연관있는 속성과 기능들을 하나의 캡슐로 만들어 데이터를 외부로부터 보호하는 것

자바에서 캡슐화를 하는 이유로 크게 두가지를 언급할 수 있다.

  1. 데이터 보호 - 외부로 부터 클래스에 정의된 속성과 기능들을 보호
  1. 데이터 은닉 - 내부의 동작은 감추고 외부에는 필요한 부분만 노출

위와 같이 알약처럼 알약 안에 어떤 내용물이 있는지 알 수 없으며 캡슐을 통해 외부로부터 오염되지 않고 보호될 수 있다.

자바의 캡슐화도 이와 같이 외부로부터 클래스에 정의된 속성과 기능들을 보호하고, 필요한 부분만 외부로 노출될 수 있도록 하여 각 객체 공유의 독립성과 책임 영역을 안전하게 지키고자하는 목적이다.

자바에서 캡슐화를 구현하기 위한 방법으로 두가지 방법이 있다.

  1. 접근제어자를 이용한 방법
  1. getter/setter 메서드

속성들을 private으로 선언하고 getter/setter 메서드의 접근제어자만이 public으로 열어둔다.

즉, 객체 간의 결합도를 낮추고 불필요한 내부 동작

2. 상속 (재사용 + 확장)

  • 상위 클래스의 특성을 하위 클래스에서 상속(재사용, 특성 상속)하고 추가로 필요한 특성을 더하는 확장 한다는 의미이다.
  • 상속 관계에서 반드시 만족해야 할 문장은 다음과 같다.
    • 하위 클래스는 상위 클래스다.
  • 상속 관계는 is-a 관계로 많이 설명되고 있지만 객체(클래스의 인스턴스)와 클래스의 관계로 오해될 소지가 많아 오해가 없도록 더 명확하게 하면 좋다.
    • 객체 is a 클래스
    • 김연아 is a 사람 → 김연아는 한 명의 사람이다.
    • 뽀로로 is a 펭귄 → 뽀로로는 한 마리 펭귄이다.
    • 하위 클래스 is a kind of 상위 클래스
    • 펭귄 is a kind of 조류 → 펭귄은 조류의 한 분류다.
    • 펭귄 is a kind of 동물 → 펭귄은 동물의 한 분류다.

다음과 같이 아래 세가지를 기억하도록 하자

  1. 객체 지향의 상속은 상위 클래스의 특성을 재사용하는 것이다.
  1. 객체 지향의 상속은 상위 클래스의 특성을 확장하는 것이다.
  1. 객체 지향의 상속은 is a kind of 관계를 만족해야 한다.

# 상속(is a kind of)와 인터페이스(is able to)

위와 같이 인어라는 클래스는 사람클래스와 물고기 클래스 모두를 상속 받을 수 있다. 만약 인어에게 사람의 기능인 달리기를 해본다던지, 물고기 기능인 아가미로 숨을 셔보라든지 기능들이 상이하게 된다.

특히, 사람도 가진 기능과 물고기가 가진 기능인 헤엄치라는 기능을 수행 할때 사람의 헤엄 기능을 수행할지.. 물고기의 헤엄 기능을 수행 할지 모호해진다는 것이다.

그래서 자바는 다중 상속을 지원하지 않는 대신에 인터페이스 통해 확장한다.

구현클래스 is able to 인터페이스 → 구현 클래스는 인터페이스 할 수 있다.

상위클래스는 하위클래스에게 특성(속성과 메소드)을 상속해주고, 인터페이스는 클래스가 무엇을 할 수 있다는 기능을 구현하도록 강제한다.

3. 추상화 (모델링)

  • 추상화 = 모델링 = 자바의 class 키워드
  • 구체적인 것을 분해하여 관심 영역(애플리케이션 경계, Application Boundary)에 있는 특성만 가지고 재조합하는 것. = 모델링

모델은 실제 사물을 정확히 복제하는 게 아니라 목적에 맞게 관심 있는 특성만을 추출해서 표현하는 것.

즉, 정리하면 아래와 같다.

  1. OOP의 추상화는 모델링이다
  1. 클래스 : 객체 = 펭귄 : 뽀로로
  1. 클래스 설계에서 추상화가 사용된다.
  1. 클래스 설계를 위해서는 애플리케이션 경계부터 정해야 한다.
  1. 객체 지향에서 추상화의 결과는 클래스다.

4. 다형성 (사용 편의성)

어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질

그림으로 보면 아래와 같이 한명의 남성이 자식에게는 부모이고 회사에서는 팀장이 되듯이 상황과 환경에 따라 달라지는 것과 비슷하다고 볼 수 있다.

자바에서는 대표적인 예로 오버라이딩과 오버로딩을 얘기할 수 있다.

public class Animal {
    public String name;

    public void showName() {
        System.out.printf("안녕 나는 %s야. 반가워\n", name);
    }
}
public class Penguin extends Animal {
    public String habitat;	

    public void showHabitat() {
        System.out.printf("%s는 %s에 살아\n", name, habitat);
    }

    //오버라이딩 - 재정의: 상위클래스의 메서드와 같은 메서드 이름, 같은 인자 리스트
    public void showName() {
        System.out.println("어머 내 이름은 알아서 뭐하게요?");
    }

    // 오버로딩 - 중복정의: 같은 메서드 이름, 다른 인자 리스트
    public void showName(String yourName) {
        System.out.printf("%s 안녕, 나는 %s라고 해\n", yourName, name);
	}
}
public class Driver {
    public static void main(String[] args) {
        Penguin pororo = new Penguin();

        pororo.name = "뽀로로";
        pororo.habitat = "남극";

        pororo.showName();
        pororo.showName("초보람보");
        pororo.showHabitat();

        Animal pingu = new Penguin();

        pingu.name = "핑구";
        pingu.showName();
    }
}

위 코드를 실행하면 pororo 객체 참조 변수를 생성하고 Penguin 객체를 만들어 연결해주면 아래와 같은 T메모리 구조를 갖는다.

Penguin 클래스에서 showName 메소드를 오버라이딩하여 Animal 클래스의 showName메소드가 덮어질걸 볼 수 있다.

따라서, pororo.showName을 호출하면 Penguin 클래스에서 재정의한 showName메소드가 실행된다.

Animal pingu = new Penguin(); 가 실행된 T메모리 구조는 위와 같으며 pingu객체 참조 변수 타입은 Animal이기 때문에 Animal 객체를 가리킨다.

하지만, 생성한 구현체는 Penguin이기 때문에 pororo와 마찬가지로 Penguin에서 재정의한 showName 메소드가 호출된다.

따라서, 다형성은 개발자가 코드를 작성할때 사용 편의성을 준다.

6. 결론

  • 객체 지향 프로그래밍의 기본적인 개념과 4가지 특성을 살펴보았다.
  • 아래와 같이 표현하게 되면 주방도구를 이용해 우리는 주방도구를 어떻게 사용하는지 설명서를 보고 도구를 이용해 어떻게 요리할지에 대한 레시피를 이용해 프로그램을 만들어 나가도록 해야한다.
    • 객체 지향 프로그래밍의 4대 특성 : 주방도구
    • 객체 지향 설계의 5원칙 : 주방도구의 설명서
    • 디자인 패턴 : 레시피
  • 위의 내용이 준비되면 링크를 남기도록 하자.

참고

반응형