자바 기본 | 3. 객체 지향 프로그래밍

heige·2024년 5월 20일

Java

목록 보기
17/21
post-thumbnail

절차 지향 프로그래밍1 - 시작

절차 지향 프로그래밍 vs 객체 지향 프로그래밍

프로그래밍 방식의 종류

절차 지향 프로그래밍

  • 이름 그대로 절차를 지향한다. 실행 순서를 중요하게 생각
  • 프로그램의 흐름을 순차적으로 따르며 처리한다. 즉, '어떻게'를 중심으로 프로그래밍 한다.

객체 지향 프로그래밍

  • 이름 그대로 객체를 지향한다. 객체를 중요하게 생각
  • 실제 세계의 사물이나 사건을 객체로 보고, 이러한 객체들 간의 상호작용을 중심으로 프로그래밍하는 방식이다. 즉, '무엇을' 중심으로 프로그래밍 한다.

차이점

절차 지향은 데이터와 해당 데이터에 대한 처리 방식이 분히되어 있다.
객체 지향에서는 데이터와 그 데이터에 대한 행봉(메스더)이 하나의 '객체' 안에 포함되어 있다.

문제 : 음악 플레이어 만들기

package ref.ex;

import java.util.Scanner;

public class ProductOrderMain3 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("주문 개수 입력 : ");
        int n = scanner.nextInt();
        scanner.nextLine();

        ProductOrder[] orders = new ProductOrder[n];

        for (int i = 0; i < orders.length; i++) {
            System.out.println((i + 1) + " 번째 주문 정보를 입력하세요. ");

            System.out.print("name : ");
            String productName = scanner.nextLine();

            System.out.println("price : ");
            int price = scanner.nextInt();

            System.out.println("quantity : ");
            int quantity = scanner.nextInt();
            scanner.nextLine();

            orders[i] = createOrder(productName, price, quantity);
        }

        printOrders(orders);
        int totalAmount = getTotalAmount(orders);
        System.out.println("Total : " + totalAmount);
    }

    static ProductOrder createOrder(String productName, int price, int quantity) {
        ProductOrder order1 = new ProductOrder();
        order1.productName = productName;
        order1.price = price;
        order1.quantity = quantity;
        return order1;
    }

    static void printOrders(ProductOrder[] orders) {
        for(ProductOrder order : orders) {
            System.out.println("name " + order.productName + ", price : " + order.price + ", quantity : " + order.quantity);
        }
    }

    static int getTotalAmount(ProductOrder[] orders) {
        int totalAmount = 0;
        for (ProductOrder order : orders) {
            totalAmount += order.price * order.quantity;
        }
        return totalAmount;
    }

}

절차 지향 프로그래밍2 - 데이터 묶음

package oop1;

public class MusicPlayerMain2 {
    public static void main(String[] args) {
        MusicPlayerData data = new MusicPlayerData();

        //player on
        data.isOn = true;
        System.out.println("player start");

        //volume ++
        data.volume++;
        System.out.println("player vol : " + data.volume);

        //volume ++
        data.volume++;
        System.out.println("player vol : " + data.volume);

        //volume --;
        data.volume--;
        System.out.println("player vol : " + data.volume);

        //player status
        System.out.println("status");
        if (data.isOn) {
            System.out.println("player on, vol : " + data.volume);
        } else {
            System.out.println("player off");
        }

        data.isOn = false;
        System.out.println("player off");
    }

절차 지향 프로그래밍3 - 메서드 추출

코드에서 중복되는 부분들,
재사용 되는 부분들 파악

  • 음악 플레이어 켜기, 끄기
  • 볼륨 증가, 감소
  • 음악 플레이어 상태 출력
package oop1;

public class MusicPlayerMain3 {
    public static void main(String[] args) {
        MusicPlayerData data = new MusicPlayerData();

        //player on
        on(data);

        //volume ++
        volumeUp(data);

        //volume ++
        volumeUp(data);

        //volume --;
        volumeDown(data);

        //player status
        showStatus(data);

        //off player
        off(data);
    }

    static void on(MusicPlayerData data) {
        data.isOn = true;
        System.out.println("player start");
    }

    static void off(MusicPlayerData data) {
        data.isOn = false;
        System.out.println("player off");
    }

    static void volumeUp(MusicPlayerData data) {
        data.volume++;
        System.out.println("volume : " + data.volume);
    }

    static void volumeDown(MusicPlayerData data) {
        data.volume--;
        System.out.println("volume : " + data.volume);
    }

    static void showStatus(MusicPlayerData data) {
        System.out.println("player status");
        if (data.isOn) {
            System.out.println("player on, volume : " + data.volume);
        } else {
            System.out.println("player off");
        }
    }

}
  • 중복 제거
  • 변경 영향의 범위 : 기능 수정 시 메서드 내부만 변경
  • 메서드 이름 추가 : 메서드 이름 통해 코드 이해 수월해짐

절차 지향 프로그래밍의 한계

데이터와 기능이 분리되어 있다는 점이다.
플레이어의 데이터는 MusicPlayerData에 있는데, 그 데이터를 사용하는 기능은 MusicPlayerMain3에 있는 각각의 메서드에 분리ㅗ디어 있다. 그래서 데이터는 MusicPlayerData를 사용하고, 플레이어 관련된 기능은 MusicPlayerMain3의 메서드를 사용해야 한다.

이후 데이터가 변경 되면 MusicPlayerMain3의 메서드들도 함께 변경해야 한다. 데이터와 기능이 분리되어 있으면 유지보수 관점에서도 관리 포인트가 두 곳으로 늘어난다.

객체 지향 프로그래은 데이터와 기능을 온전히 하나로 묶어서 사용할 수 있다

클래스와 메서드

클래스는 데이터인 멤버 변수 뿐 아니라 기능 역할을 하는 메서드도 포함할 수 있다.

package oop1;

public class valueData {
    int value;
}

package oop1;

public class valueDataMain {
    public static void main(String[] args) {
        valueData valueData = new valueData();
        add(valueData);
        add(valueData);
        add(valueData);
        System.out.println("최종 = " + valueData.value);
    }

    static void add(valueData valueData) {
        valueData.value++;
        System.out.println("숫자 증가 value = " + valueData.value);

    }
}

위 코드를 보면 valuevalue를 증가시키는 add() 메서드가 서로 분리되어 있다.
자바와 같은 객체지향언어는 클래스 내부에 속성(데이터)과 기능(메서드)을 함께 포함할 수 있다. 클래스 내부에 멤버 변수 뿐만 아니라 메서드도 함께 포함할 수 있다는 듯이다.

package oop1;

public class ValueObject {
    int value;
    void add() {
        value++;
        System.out.println("숫자 증가 value = " + value);
    }
}

c.f

  • void add()static 을 사용하지 않은 이유
    메서드는 객체를 생성해야 호출할 수 있다. 그런데 static 이 붙으면 객체를 생성하지 않고도 메서드를 호출할 수 있다.
package oop1;

public class ValueObjectMain {
    public static void main(String[] args) {
        ValueObject valueObject = new ValueObject();

        valueObject.add();
        valueObject.add();
        valueObject.add();
        System.out.println("최종 = " + valueObject.value);
    }
}

인스턴스 생성

ValueObject valueObject = new ValueObject();

valueObject 라는 객체를 생성하면, 이 객체에는 멤버 변수 뿐만 아니라 내부에 기능을 수행하는 add() 메서드도 함께 존재한다.

인스턴스의 메서드 호출

인스턴스의 메서드를 호출하는 방법은 멤버 변수를 사용하는 방법과 동일. . (dot)을 찍어서 객체 접근한 다음에 원하는 메서드를 호출하면 된다.

valueObject.add(); //1
x002.add(); //2: x002 ValueObject 인스턴스에 있는 add() 메서드를 호출한다.

정리

  • 클래스는 속성(데이터, 멤버 변수)과 기능(메서드)을 정의할 수 있다.
  • 객체는 자신의 메서드를 통해 자신의 멤버 변수에 접근할 수 있다.
    *
    • 객체의 메서드 내부에서 접근하는 멤버 변수는 객체 자신의 멤버 변수이다.

객체 지향 프로그래밍

객체 지향 음악 플레이어

package oop1;

import org.w3c.dom.ls.LSOutput;

public class MusicPlayer {
    int volume = 0;
    boolean isOn = false;

    void on() {
        isOn = true;
        System.out.println("player start");
    }

    void off() {
        isOn = false;
        System.out.println("player off");
    }

    void volumeUp() {
        volume++;
        System.out.println("volume : " + volume);
    }

    void volumeDown() {
        volume--;
        System.out.println("volume : " + volume);
    }

    void showStatus() {
        System.out.println("player status : ");
        if (isOn) {
            System.out.println("player on, volume : " + volume);
        } else {
            System.out.println("player off");
        }
    }
}
package oop1;

public class MusicPlayerMain4 {
    public static void main(String[] args) {
        MusicPlayer player = new MusicPlayer();

        player.on();
        player.volumeUp();
        player.volumeUp();
        player.volumeDown();
        player.showStatus();
        player.off();
    }
}

캡슐화

MusicPlayer을 보면 속성과 기능이 하나의 캡슐에 쌓여있는 것 같다. 이렇게 속성과 기능을 하나로 묶어서 필요한 기능을 메서드를 통해 외부에 제공하는 것을 캡슐화라고 한다.

문제와 풀이

문제 1 - 절차 지향 직사각형 프로그램을 객체지향으로 변경

package oop1.ex;

public class Rectangle {
    int width;
    int height;

    int caculateArea() {
        return width * height;
    }
    int calculatePerimeter() {
        return 2 * (width + height);
    }
    boolean isSquare() {
        return width == height;
    }
}
package oop1.ex;

public class RectangleMain {
    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle();
        rectangle.width = 5;
        rectangle.height = 8;

        int area = rectangle.caculateArea();
        System.out.println("area : " + area);

        int perimeter = rectangle.calculatePerimeter();
        System.out.println("perimeter : " + perimeter);

        boolean square = rectangle.isSquare();
        System.out.println("squere? : " + square);

    }
}

문제 2 - 객체 지향 계좌

package oop1.ex;

public class Account {
    int balance;
    void deposit(int amount) {
        balance += amount;
    }
    void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount;
        } else {
            System.out.println("잔액 부족");
        }
    }
}
package oop1.ex;

public class AccountMain {
    public static void main(String[] args) {
        Account account = new Account();

        account.deposit(10000);
        account.withdraw(9000);
        account.withdraw(2000);

        System.out.println("잔고 : " + account.balance);
    }
}

정리

절차지향 vs 객체지향

  • 절차 지향은 데이터와 해당 데이터에 대한 처리 방식이 분리되어 있다.
  • 객체 지향에서는 데이터와 그 데이터 에 대한 행동(메서드)이 하나의 '객체' 안에 함께 포함되어 있다.
profile
웹 백엔드와 클라우드 정복을 위해 탄탄한 기반을 쌓아가고 있는 예비개발자입니다. 'IT You Up'은 'Eat You Up'이라는 표현에서 비롯되어, IT 지식을 끝까지 먹어치운다는 담고 있습니다.

0개의 댓글