객체지향 프로그래밍(Object-Oriented Programming, OOP)

By | 2020년 5월 22일
Table of Contents

객체지향 프로그래밍(Object-Oriented Programming, OOP)

– 객체지향 프로그래밍이란 무엇인가?

객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임중 하나로, 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행동을 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.

라고 하는데… 복잡하군요. 하나씩 풀어보도록 합니다.

– 객체란 무엇인가?

객체

일반적으로 명사가 객체가 됩니다.

쇼핑몰에서, 고객이 상품을 장바구니에 담는다 라는 로직을 구현해 봅니다.

public class Customer { /* ... */ }

public class Product { /* ... */ }

public class ShoppingCart { /* ... */ }

public class TicketProduct extends Product { /* ... */ }

명사인 고객, 상품, 장바구니 가 각각 객체가 됩니다.

객체와 클래스가 자주 오해를 가져오는데… 간단히 객체는 개념이고, 클래스는 자바에서 사용하는 구현체입니다. javascript 같은 경우 class 가 아니라 function 이 객체의 기능을 하게 됩니다.

상태와 행동

상태와 행동을 가진 객체 는 무슨 의미일까요?

행동은 객체의 존재 이유입니다. 위에서는 장바구니에 담는 것 이 행동이 됩니다. 그리고, 상태는 행동에 의해 변경되는 데이타의 모음입니다.

String userId = "skyer9@gmail.com";
long toyId = 11112222;
long bookId = 33334444;
long ticketId = 55556666;
LocalDateTime showTime = LocalDateTime.of(2020, 5, 15, 17, 30);

Customer customer = new Customer(userId);
Product toy = new Product(toyId, "장난감", new BigDecimal(5000));
Product book = new Product(bookId, "책", new BigDecimal(20000));
TicketProduct ticket = new TicketProduct(ticketId, "티켓", new BigDecimal(12000), showTime);

customer.addToCart(toy);
customer.addToCart(book);
customer.addToCart(ticket);

여기서 중요한 것은 행동이 먼저이고, 상태는 부수적인 것이라는 점입니다.

addToCart() 를 구현하다 보니 CustomerShoppingCart 를 가지고 있어야 하는 것이지, 그 반대는 아니라는 것입니다.

– 추상화와 캡슐화

추상화(자료의 추상화)

위에서 Customer 가 상품정보를 어떤 형태로 보관하고 있는지는 다른 객체는 전혀 알 수 없습니다.(물론 알 필요도 없습니다.)

이런 추상화가 불편해 보일 수 있지만 캡슐화 를 설명하면서 왜 좋은 특징이 되는지 설명합니다.

캡슐화

데이타가 추상화 되어 있기 때문에 Customer 객체는 다른 객체를 전혀 고려하지 않고 자유로이 상품정보의 보관방식을 변경할 수 있습니다.

ArrayList<Product> 에 막바로 보관할 수도 있고, ShoppingCart 객체를 생성해서 보관할 수도 있습니다.

소스의 변경이 필요한 시점에 고려해야 할 범위를 제한할 수 있다는 것은 매우 좋은 장점이 됩니다.

– 상속

상속은 부모객체의 속성과 기능을 그대로 이어받아 사용할 수 있게하고, 기능의 일부분을 변경해야 할 경우, 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것입니다.

public class TicketProduct extends Product {
    private LocalDateTime showTime;

    public TicketProduct(long productId, String productName, BigDecimal price, LocalDateTime showTime) {
        super(productId, productName, price);
        this.showTime = showTime;
    }
}

TicketProductProduct 을 상속받아 공연시간을 추가하고 있습니다.

상속과 사용

여기서 구분해야 할 것은 상속사용 입니다.

객체 자체를 확장해서 쓸 때는 상속을 해야하고, 객체를 단지 이용만 하는 경우(위에서 Customer 가 ShoppingCart 를 이용하는 경우)는 상속이 아니라, 속성에 객체를 추가해서 사용하기만 하면 됩니다.

상속(extends) 과 인터페이스(interface)

상속과 유사하지만 구별되는 것이 interface 입니다. 상속은 코드를 공유하지만, interface 는 코드의 공유가 전혀 없는 것이 차이점입니다.

– 다형성

오버라이딩(Overriding)

부모 객체의 메소드를 재정의하는 것을 말합니다.

public class Money {
    // ...
    @Override
    public String toString() {
        return "wallet.Money{" +
                "amount=" + amount +
                ", currencyCode='" + currencyCode + '\'' +
                '}';
    }
}

public class Mileage extends Money {
    // ...
    @Override
    public String toString() {
        return "wallet.Mileage{" +
                "amount=" + this.getAmount() +
                ", currencyCode='" + this.getCurrencyCode() + '\'' +
                '}';
    }
}

오버로딩(Overloading)

동일한 메소드명으로, 서로 다른 타입 또는 갯수의 파라미터를 받는 것을 말합니다.

public class Money {
    // ...

    public Money add(Money _amount) {
        // ...
    }

    public Money add(long _amount) {
        // ...
    }

    public Money add(BigDecimal _amount) {
        // ...
    }
    // ...
}

위에서 보면 add() 함수는 여러 파라미터를 받고 있습니다.

답글 남기기