Idea

객체지향 이해하기

문쿼리 2025. 4. 16. 00:38

(내가 나를 가르치는 글이라 반말입니다)

자동차가 가진 속성이 뭘까? 색상, 브랜드, 제조일자, 몇인승, 튜닝여부, 현재 속도, 운전중/주차중, 키로 수, 연료량 등

행위는? 가속하기, 정지하기, 멈추기, 주유하기, 세차하기, 수리하기 등이 있을것이다

클래스로 만들어보자

public class Car {
    private String name;
    private int speed;

    public Car(String name) {
    	this.name = name;
        this.speed = 0;
    }

    public void accelerate() {
        speed += 10;
        System.out.println(name + " 차 가속! 속도: " + speed);
    }

    public void brakePedals() {
        speed -= 10;
        System.out.println(name + " 차 감속! 속도: " + speed);
    }
}

 

클래스로 보면 이런 형태가 된다. 여기서 속성은 외부에서 변경할 수 없는 속성이고, 행위를 통해 속성을 변경할 수 있다.

=> 캡슐화

 

나는 전기차가 필요하다

public class ElectricCar extends Car {
    private int battery;

    public ElectricCar(String name) {
        super(name);
        this.battery = 100;
    }

    public void charge() {
        this.battery = 100;
        System.out.println("완충!");
    }
}

자동차를 상속 받은 전기차는 자동자의 기본 기능을 그대로 사용할 수 있고, 전기차 만의 기능을 사용할 수 있다.

=> 상속

 

운전을 해보자

public class DriveCar {
    public static void main(String[] args) {
        Car myCar = new Car("부릉부릉");
        Car myElecCar = new ElectricCar("찌릿찌릿");

        myCar.accelerate();
        myCar.stop();

        myElecCar.accelerate(); // Car로 선언했지만 ElectricCar의 동작 가능 (다형성)
    }
}

new ElectricCar();로 Car를 만들 수 있다. 마찬가지로 Car를 상속받은 어떠한 객체들도 동일하게 생성 할 수 있다.

=> 다형성

 

그냥 차도 좋아, 근데 모든 차는 에너지 보충이 필요하단 말이야

전기차는 전기 충전을 구현해야하고, 가솔린차는 가솔린 충전을 해줘야하는데 하나하나 넣는건 관리가 복잡하네

구현에 강제성을 줘서 협업과 유지보수를 편하게 하자

=> 상속 + 추상화

 

기존의 Car를 추상 클래스로 변경해보자

public abstract class AbstractCar {
    protected String name;
    protected int speed;

    public AbstractCar(String name) {
        this.name = name;
        this.speed = 0;
    }

    public void accelerate() {
        speed += 10;
        System.out.println(name + " 차 가속! 속도: " + speed);
    }

    public void brakePedals() {
        speed -= 10;
        System.out.println(name + " 차 감속! 속도: " + speed);
    }

    public abstract void chargeEnergy();	// 상속받은 객체들의 공통, 각각 기능은 다를 수 있다.
}

 

전기차 다시 만들어야해

public class ElectricCar extends AbstractCar {
    private int battery;

    public ElectricCar(String name) {
        super(name);
        this.battery = 100;
    }

    @Override
    public void chargeEnergy() {
        battery = 100;
        System.out.println(name + " 충전 완");
    }
}

 

가솔린차도 만들자

public class GasolineCar extends AbstractCar {
    private int fuel;

    public GasolineCar(String name) {
        super(name);
        this.fuel = 100;
    }

    @Override
    public void chargeEnergy() {
        fuel = 100;
        System.out.println(name + " 주유 완");
    }
}

 

새차로 운전해보자

public class DriveCar {
    public static void main(String[] args) {
        AbstractCar gasCar = new Car("가스가스");
        AbstractCar elecCar = new ElectricCar("찌릿찌릿");

        gasCar.refuel();
        gasCar.accelerate();
        gasCar.stop();
        
        elecCar.refuel();
        elecCar.accelerate();
        elecCar.stop();
    }
}

refuel만으로 가솔린이 채워지는지 배터리가 채워지는지는 모르지만 행위로 여러 객체를 동일하게 다룰 수 있지

=> 다형성

 

만들다 보니 차말고, 배도 만들어야하네? 근데 배도 충전해야하잖아

AbstractCar를 쓰자고 할건 아니지? 충전이 필요한 객체의 추상은 아니잖아

이럴 땐 인터페이스를 쓰자

=> 추상화(+다형성)

public interface EnergyRechargeable {
    void chargeEnergy(); // 에너지를 보충하는 기능
}

 

배도 만들고 차도 만들어보자

public class Ship implements EnergyRechargeable {
    private String name;
    private int fuel;

    public Ship(String name) {
        this.name = name;
        this.fuel = 100;
    }

    @Override
    public void chargeEnergy() {
        fuel = 100;
        System.out.println(name + " 주유 완");
    }
}
public class GasolineCar implements EnergyRechargeable {
    private String name;
    private int fuel;

    public GasolineCar(String name) {
        this.name = name;
        this.fuel = 100;
    }

    @Override
    public void chargeEnergy() {
        fuel = 100;
        System.out.println(name + " 주유 완");
    }
}

 

주유소에서 주유를!

public class RechargeStation {
    public void recharge(EnergyRechargeable target) {
        System.out.println("주유!");
        target.chargeEnergy(); // 어떤 탈것이든 chargeEnergy만 있으면 동작 가능!
    }
}

public class RechargeService {
    public static void main(String[] args) {
        EnergyRechargeable car = new ElectricCar("찌릿찌릿");
        EnergyRechargeable ship = new Ship("통통통");

        RechargeStation station = new RechargeStation();

        station.recharge(car);
        station.recharge(ship);
    }
}

이제 상속과 추상화 다형성이 밀접하다는게 느껴지지?

 

위 코드들을 조합해서 다형성을 뽑아보자

EnergyRechargeable ship = new Ship("통통통통"); // 인터페이스 기반
AbstractCar car = new ElectricCar("찌릿짜릿"); // 추상 클래스 기반

ship.chargeEnergy();
car.chargeEnergy();	// 인터페이스, 추상 모두 다형성을 발생

 

아 무슨 또 비행기를 만드십니까? 

이동 수단을 상속하고 에너지 충전은 인터페이스로 설계해서 Car, Ship, Plane을 구현해보자

EnergyRechargeable 는 그대로 쓸거야

public abstract class Vehicle {
    protected String name;
    protected int speed;
    private String howToMove; // 어떻게 이동하는지

    public Vehicle(String name, String howToMove) {
        this.name = name;
        this.speed = 0;
        this.howToMove = howToMove;
    }

    public void accelerate() {
        speed += 10;
        System.out.println(name + " 가속! 속도: " + speed);
    }

    public void brake() {
        speed -= 10;
        System.out.println(name + " 감속! 속도: " + speed);
    }

    public String getHowToMove() {
        return howToMove;
    }

    public abstract void move();
}
public class Car extends Vehicle implements EnergyRechargeable {
    private int fuel;

    public Car(String name) {
        super(name, "도로를 달린다");
        this.fuel = 100;
    }

    @Override
    public void chargeEnergy() {
        fuel = 100;
        System.out.println(name + " 주유 완");
    }

    @Override
    public void move() {
        System.out.println(name + ": " + getHowToMove());
    }
}
public class Plane extends Vehicle implements EnergyRechargeable {
    private int fuel;

    public Plane(String name) {
        super(name, "하늘을 날아다닌다");
        this.fuel = 100;
    }

    @Override
    public void chargeEnergy() {
        fuel = 100;
        System.out.println(name + " 연료 충전 완");
    }

    @Override
    public void move() {
        System.out.println(name + ": " + getHowToMove());
    }
}

 

달려라 달려

public class Drive {
    public static void main(String[] args) {
        Vehicle car = new Car("부릉부릉");
        Vehicle plane = new Plane("슝슝슝슝");
        Vehicle ship = new Ship("통통통통");

        RechargeStation station = new RechargeStation();

        station.recharge((EnergyRechargeable) car);
        station.recharge((EnergyRechargeable) plane);
        station.recharge((EnergyRechargeable) ship);

        car.accelerate();
        car.move();   // 출력: 부릉부릉: 도로를 달린다

        plane.accelerate();
        plane.move(); // 출력: 슝슝슝슝: 하늘을 날아다닌다
        
        ship.accelerate();
        ship.move();  // 출력: 통통통통: 바다 위를 떠다닌다
    }
}

이런 구조를 가지면 Ship 클래스를 확인해보지 않아도 추론이 가능하다는 장점이 있어

 

객체지향은 단순한 문법이 아니라, 복잡한 문제를 유연하게 풀어내는 사고방식이야.
코드를 통해 현실 세계의 구조와 개념을 자연스럽게 녹여낼 수 있고,
캡슐화를 통해 데이터 보호와 제어가 가능하며, 상속은 공통 기능을 재사용하게 해줘.
추상화와 다형성은 변화에 강한 유연한 구조를 만들 수 있도록 도와주지.

결국 객체지향은 기능의 분리나 역할의 명확화를 넘어서,
유지보수와 확장성, 그리고 일관성 있는 협업 환경까지 만들어주는 강력한 개발 철학이기 때문에,
꼭 이해하고 체화할 필요가 있다고 생각해.

아니면 그냥 외워..!