디버깅 세션 2회차 (OOP)

SJ.CHO·2024년 9월 13일

객체를 왜 사용하는가?

  • 코드복잡성 하락, 유지보수성 상승, 재사용성 상승

객체지향적 코드

// 자동차 계기판의 정보를 관리하는 클래스
class Dashboard {

    private int speed; //속도
    private int fuelLevel; //연료
    
    public Dashboard() {
        this.speed = 0;  // 초기 속도는 0
        this.fuelLevel = 100;  // 초기 연료는 100
    }
    
    // 속도를 설정하는 메서드
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    
    // 연료량을 설정하는 메서드
    public void consumeFuel(int amount) {
        if (this.fuelLevel - amount >= 0) {
            this.fuelLevel -= amount;
        } else {
            this.fuelLevel = 0;
        }
    }
    
    // 계기판 정보를 출력하는 메서드
    public void displayDashboard() {
        System.out.println("Speed: " + this.speed + " km/h");
        System.out.println("Fuel Level: " + this.fuelLevel + " %");
    }
}


class Car {
    private String model;
    private String color;
    private Dashboard dashboard;  // 계기판 객체 포함

    public Car(String model, String color) {
        this.model = model;
        this.color = color;
        this.dashboard = new Dashboard();  // 새로운 계기판 생성
    }
    
    // 속도를 올리는 메서드
    public void accelerate(int increment) {
        this.dashboard.setSpeed(this.dashboard.speed + increment);  // 속도 증가
        this.dashboard.consumeFuel(5);  // 가속할 때마다 연료 5 소비
    }
    
    // 현재 자동차 상태를 계기판으로 출력하는 메서드
    public void displayStatus() {
        System.out.println("Model: " + this.model + ", Color: " + this.color);
        dashboard.displayDashboard();  // 계기판 정보 출력
    }
}

public class Main {
    public static void main(String[] args) {
        Car car1 = new Car("Tesla", "Red");
        Car car2 = new Car("BMW", "Blue");
        
        // Tesla 가속
        car1.accelerate(60);
        car1.displayStatus();  // Tesla의 상태 출력
        
        // BMW 가속
        car2.accelerate(30);
        car2.displayStatus();  // BMW의 상태 출력
    }
}
  • car class 와 dashboard class의 분리로 객체별 책임을 분리 유지보수성이 높아진다.
  • 하나 class의 기능이 추가되거나 변경되도 영향이 가지않는다.
  • 모든객체를 수정할 필요성이 없어짐.

절차적 코드

public class Main {
    // 자동차의 상태를 저장하는 변수들
    static String car1Model = "Tesla";
    static String car1Color = "Red";
    static int car1Speed = 0;
    static int car1FuelLevel = 100;

    static String car2Model = "BMW";
    static String car2Color = "Blue";
    static int car2Speed = 0;
    static int car2FuelLevel = 100;

    // 자동차의 속도를 증가시키는 함수
    public static void accelerate(int increment, String model) {
        if (model.equals(car1Model)) {
            car1Speed += increment;
            car1FuelLevel -= 5;
        } else if (model.equals(car2Model)) {
            car2Speed += increment;
            car2FuelLevel -= 5;
        }
    }

    // 계기판 상태를 출력하는 함수
    public static void displayDashboard(String model) {
        if (model.equals(car1Model)) {
            System.out.println("Model: " + car1Model + ", Color: " + car1Color);
            System.out.println("Speed: " + car1Speed + " km/h");
            System.out.println("Fuel Level: " + car1FuelLevel + " %");
        } else if (model.equals(car2Model)) {
            System.out.println("Model: " + car2Model + ", Color: " + car2Color);
            System.out.println("Speed: " + car2Speed + " km/h");
            System.out.println("Fuel Level: " + car2FuelLevel + " %");
        }
    }

    public static void main(String[] args) {
        // Tesla 가속
        accelerate(60, car1Model);
        displayDashboard(car1Model);

        // BMW 가속
        accelerate(30, car2Model);
        displayDashboard(car2Model);
    }
}
  • 자동차별 변수네임을 통해서 필드를 관리해야함.
  • 중복코드들이 발생, 유지보수성싱 낮다.

차이점

  • Class 하나의 책임을 많이 주면 의존성이 너무 높아지고 확장성이 낮아진다.
  • 책임의 분리로 인한 기능의 독립성이 올라간다.
  • 하나의 클래스로 여러 객체를 만들어 동일하게 사용이 가능.
    (기능의 추가와 변경을 Class 로만 변경가능)
  • 객체에 대한 책임분리는 기준과 기획서의 따라 달라짐
  • 너무 상세하게 쪼갤시 유지보수와 협업에서의 관점에서 불리

객체의특징 4가지

캡슐화

class Car {
	  private String model;  // 외부에서 접근할 수 없음
    private int fuelLevel; // 외부에서 접근할 수 없음
    private int speed;

    // 생성자
    public Car(String model) {
        this.model = model;
        this.speed = 0;  // 기본 속도는 0
    }

    // 외부에서 속도를 변경할 수 있는 메서드 제공
    public void accelerate(int increment) {
        if (increment > 0) {
            this.speed += increment;
        }
    }

    // 현재 속도를 반환하는 메서드
    public int getSpeed() {
        return this.speed;
    }
}
  • 객체의 필드와 메서드를 하나의 단위를 묶고, 외부에서 직접접근을 막음. (접근 제어자)
  • 원하는 필드, 메서드만 외부로 열어줄수 있음.

상속

class Car {
    private int speed;
    private int fuelLevel;

    public Car() {
        this.speed = 0;
        this.fuelLevel = 100;
    }

    public void accelerate(int increment) {
        this.speed += increment;
        this.fuelLevel -= 5;
    }

    public void displayStatus() {
        System.out.println("Speed: " + speed + " km/h");
        System.out.println("Fuel Level: " + fuelLevel + " %");
    }
}

// Tesla는 Car 클래스를 상속받음
class Tesla extends Car {
		private boolean autonomousDrivingMode;


    @Override
    public void accelerate(int increment) {
        super.accelerate(increment * 2);  // Tesla는 속도가 두 배로 증가
    }
    
    
    public void setAutonomousDrivingMode() {
		    this.autonomousDrivingMode = true
    }
    
    //...

}
  • 부모클래스의 멤버를 자식클래스가 상속받아서 사용하고 필요시 기능을 추가하거나 재정의 가능 (@Override).
  • 상속이 없었다면 자동차 객체마다 계속 코드를 작성해야함.

추상화

abstract class Car {
    protected int speed;
    protected int fuelLevel;

    public Car() {
        this.speed = 0;
        this.fuelLevel = 100;
    }

    // 추상 메서드: 각 자동차마다 가속 방식이 다를 수 있음
    public abstract void accelerate();

    public void displayStatus() {
        System.out.println("Speed: " + speed + " km/h");
        System.out.println("Fuel Level: " + fuelLevel + " %");
    }
}

class Tesla extends Car {
    @Override
    public void accelerate() {
        speed += 60;  // Tesla는 60씩 가속
        fuelLevel -= 5;
    }
}

class BMW extends Car {
    @Override
    public void accelerate() {
        speed += 30;  // BMW는 30씩 가속
        fuelLevel -= 5;
    }
}
  • Java에서는 abstract or interface 키워드를 활용하여 추상화
  • 복잡한 내부로직을 감추고 상위클래스에서 필요한 부분만 외부에 노출함.
  • 구현클래스들이 필요한부분을 추가적으로 구현.
  • 구조적인 부분만 정의를 하고 하위클래스에게 구현을 하게 만들수있음
    (Interface의 경우 구현의 강제성을 띄기에 무조건 구현해야함)

다형성

public class Main {
    public static void main(String[] args) {
        Car tesla = new Tesla();  // Car 타입으로 Tesla 객체 생성
        Car bmw = new BMW();  // Car 타입으로 BMW 객체 생성

        tesla.accelerate();  // Tesla의 accelerate() 호출
        bmw.accelerate();  // BMW의 accelerate() 호출

        tesla.displayStatus();
        bmw.displayStatus();
    }
}
  • 메서드 행위자체가 동일할때 객체가 호출시 결과가 달라지는 현상.
  • 일관된 인터페이스로 다양한 객체를 제어할 수 있다.
  • 다형성을 사용하면 하나의 명령어를 다양한 방식으로 처리할 수 있어, 코드의 유연성과 확장성을 극대화
  • 새로운 기능을 추가하거나 변경할 때도 간단히 확장할 수 있어 유지보수에 유리하며, 코드를 보다 효율적으로 관리
profile
70살까지 개발하고싶은 개발자

0개의 댓글