[아이티센 부트캠프] (객체지향)

이언덕·2026년 3월 22일

아이티센 부트캠프

목록 보기
10/115
post-thumbnail

[객체지향 OOP]

지금부터는 기능만 따로 만드는 방식에서 한 걸음 더 나아가,
프로그램에서 다루고 싶은 대상을 중심으로 코드를 만드는 방법을 배우게 된다.

이번 파트는 아래 흐름으로 이해하면 된다.

객체지향 → 클래스와 객체 → 객체의 구성 요소 → 객체 생성과 사용 → 객체배열 → 생성자

이 순서를 먼저 잡아두면 뒤에서 나오는 내용이 훨씬 덜 헷갈린다.




1. 객체지향 프로그래밍 OOP

개념

객체지향은 프로그램에서 다루고 싶은 대상을 중심으로 생각하는 방식이다.
그리고 그 대상에 필요한 정보와 기능을 하나로 묶어서 표현한다.

예를 들어 자동차를 프로그램으로 표현한다고 해보자.

자동차는

  • 색상
  • 속도
  • 브랜드

같은 정보를 가질 수 있고,

  • 출발하기
  • 멈추기
  • 속도 올리기

같은 기능도 할 수 있다.

객체지향은 이런 식으로
하나의 대상에 필요한 정보와 기능을 따로 흩어 놓지 않고 함께 묶어서 다루는 방식이다.

즉, 객체지향은
“무슨 기능을 만들지”만 먼저 보는 것이 아니라, “어떤 대상을 만들고 다룰지”를 먼저 생각하는 방식이라고 이해하면 된다.



핵심 특징

  • 정보와 기능을 하나로 묶어서 관리한다.
  • 관련 있는 코드가 한곳에 모여서 보기 쉬워진다.
  • 같은 구조를 여러 번 재사용하기 좋다.
  • 기능을 수정하거나 확장할 때 관리가 편하다.
  • 코드 재사용성이 높아지고, 유지보수도 쉬워진다.



자동차 예시로 이해하기

여기서 자동차는 그냥 예시로 나온 말이 아니다.
자바에서는 실제로 자동차라는 대상을 만들기 위한 클래스를 만들 수 있다.

그리고 그 클래스를 이용해서 실제 객체를 만들 수 있다.

예를 들면

  • 자동차 → 클래스
  • 포르쉐 → 객체
  • 페라리 → 객체

이렇게 이해할 수 있다.


즉, 자동차는 자동차를 만들기 위한 틀이고,
포르쉐, 페라리는 그 틀로 만들어진 실제 대상이다.

중요한 점은
같은 자동차 클래스로 만들었더라도 각 객체는 서로 다른 값을 가질 수 있다는 것이다.

예를 들어

  • 포르쉐 객체는 색상 = 빨강, 속도 = 120
  • 페라리 객체는 색상 = 노랑, 속도 = 150

처럼 각각 다른 상태를 가질 수 있다.



헷갈리기 쉬운 부분

처음에는 자동차, 포르쉐, 페라리를 모두 같은 수준으로 보기 쉽다.
하지만 객체지향에서는 역할이 다르다.

  • 자동차는 틀
  • 포르쉐, 페라리는 그 틀로 만든 실제 객체

이 차이를 먼저 확실히 잡아야 한다.




2. 클래스와 객체

개념

자바에서는 프로그램에서 다루고 싶은 대상을 바로 만드는 것이 아니라,
먼저 그 대상을 만들기 위한 틀을 만든다.
이 틀이 클래스다.

그리고 그 클래스를 이용해서 실제로 만들어진 대상을 객체라고 한다.

쉽게 말하면

  • 클래스는 설계도
  • 객체는 설계도로 만든 실제 결과물

이다.


앞에서 본 예시로 다시 보면,

  • 자동차는 클래스
  • 포르쉐, 페라리는 객체

다.



핵심 특징

  • 클래스는 객체를 만들기 위한 틀이다.
  • 객체는 클래스로 만든 실제 사용 대상이다.
  • 클래스 하나로 객체를 여러 개 만들 수 있다.
  • 같은 클래스로 만든 객체라도, 각 객체의 값은 서로 다를 수 있다.



코드 예제

예제: CarTest1

class Car {
    String brand;
    String color;
    int speed;
}

public class CarTest1 {
    public static void main(String[] args) {
        Car car1 = new Car();
        Car car2 = new Car();
    }

    // 출력결과
    // 없음
}

이 코드는 Car라는 틀을 만들고,
그 틀로 car1, car2라는 실제 객체를 만든 가장 기본적인 형태다.



헷갈리기 쉬운 부분

Car가 자동차 한 대는 아니다.
Car는 자동차를 만들기 위한 틀이고, car1, car2가 실제 객체다.

또 객체와 인스턴스는 초반에는 거의 비슷하게 생각해도 된다.
다만 조금 더 정확히 말하면, 인스턴스는 어떤 클래스에서 만들어졌는지를 강조하는 표현이다.

예를 들어

  • car1은 객체다
  • car1은 Car 클래스의 인스턴스다

둘 다 맞는 말이다.




3. 객체의 구성 요소

개념

객체지향에서는 하나의 대상을 정보와 기능으로 나누어 표현한다.

예를 들어 자동차라는 대상이 있다면,

  • 정보: 브랜드, 색상, 속도
  • 기능: 출발하기, 멈추기, 속도 올리기

처럼 생각할 수 있다.

자바에서는 이런 것을 아래처럼 만든다.

  • 정보 → 멤버변수
  • 기능 → 메서드

즉, 객체지향에서는
객체가 가져야 할 상태는 멤버변수로 표현하고, 객체가 해야 할 동작은 메서드로 표현한다고 이해하면 된다.

그리고 자바에서는 이런 정보와 기능을 클래스 안에 정의해 두고,
그 클래스로부터 실제 객체를 만들어 사용한다.





핵심 특징

  • 멤버변수는 객체의 상태를 저장한다.
  • 메서드는 객체가 할 수 있는 동작을 만든다.
  • 객체지향에서는 정보와 기능을 따로 흩어 놓지 않고 하나의 클래스 안에 함께 묶는다.
  • 같은 클래스로 여러 객체를 만들 수 있고, 객체마다 멤버변수 값은 서로 다를 수 있다.



코드 예제

예제: CarTest2

class Car {
    String brand;
    String color;
    int speed;

    void drive() {
        System.out.println(brand + " 자동차가 출발합니다.");
    }

    void stop() {
        System.out.println(brand + " 자동차가 멈춥니다.");
    }
}

public class CarTest2 {
    public static void main(String[] args) {

    }

    // 출력결과
    // 없음
}

이 코드는 자동차라는 대상을 자바 클래스 안에 어떻게 표현하는지 보여준다.

  • brand, color, speed는 자동차의 정보를 저장하는 멤버변수
  • drive(), stop()은 자동차의 동작을 만드는 메서드

다.

즉, 자바에서는 객체가 가져야 할 정보와 기능을
이렇게 클래스 안에 멤버변수와 메서드로 미리 정의해 두는 것이다.



헷갈리기 쉬운 부분

여기서 멤버변수와 메서드는 객체 안에 들어 있는 것처럼 설명하지만,
실제로 코드를 작성할 때는 클래스 안에 정의한다.

즉,

  • 개념으로 보면 → 객체는 정보와 기능을 가진다
  • 코드로 보면 → 그 정보와 기능을 클래스 안에 멤버변수와 메서드로 만든다

이렇게 이해하면 된다.

또 처음에는 멤버변수와 메서드를 따로 외우기보다,
“객체의 정보는 변수로, 객체의 기능은 메서드로 만든다”
이 흐름으로 잡는 것이 더 중요하다.




4. 객체 생성과 사용

개념

클래스를 만들었다고 해서 바로 사용할 수 있는 것은 아니다.
실제로 쓰려면 객체를 생성해야 한다.

객체는 new를 사용해서 만든다.

Car car1 = new Car();

or     // 위 한 줄은 아래 두 줄을 한 번에 쓴 형태다.

Car car1;        // Car 객체를 가리키기 위한 참조변수 선언
car1 = new Car(); // Car 객체 생성 후, 그 객체의 참조값을 `car1`에 저장

즉

  • Car car1; → Car 클래스의 객체를 참조하기 위한 변수 선언
  • car1 = new Car(); → 실제 객체를 만든 뒤, 그 객체를 car1이 가리키게 연결

여기서는 어렵게 생각하지 말고 이렇게 이해하면 된다.

  • 객체 = 설계도로 실제 만든 자동차
  • 참조변수 = 그 자동차를 가리키는 이름표

즉, car1은 자동차 자체가 아니라,
만들어진 자동차 객체를 가리키는 이름표 같은 역할을 한다.

그리고 객체 안의 정보와 기능을 사용하려면 . 연산자를 쓴다.
예를 들면

  • car1.brand
  • car1.color
  • car1.drive()

처럼 사용한다.

즉, 참조변수 뒤에 .을 붙이면
그 객체가 가지고 있는 정보나 기능을 사용할 수 있다.



핵심 특징

  • new로 객체를 만든다.
  • 참조변수는 객체를 가리키는 이름표 같은 역할을 한다.
  • . 연산자로 멤버변수와 메서드에 접근한다.
  • 같은 클래스로 여러 객체를 만들 수 있고, 객체마다 값은 서로 다를 수 있다.



코드 예제

예제: CarTest3

class Car {
    String brand;
    String color;
    int speed;

    void drive() {
        System.out.println(brand + " 자동차가 출발합니다.");
    }

    void printInfo() {
        System.out.println("브랜드: " + brand + ", 색상: " + color + ", 속도: " + speed);
    }
}

public class CarTest3 {
    public static void main(String[] args) {
        Car car1;              // Car 객체를 가리킬 참조변수 선언
        car1 = new Car();      // 실제 Car 객체 생성 후 car1과 연결

        car1.brand = "포르쉐";  // car1이 가리키는 객체의 brand 값 저장
        car1.color = "빨강";    // car1이 가리키는 객체의 color 값 저장
        car1.speed = 120;      // car1이 가리키는 객체의 speed 값 저장

        Car car2;              // 두 번째 Car 객체를 가리킬 참조변수 선언
        car2 = new Car();      // 또 다른 Car 객체 생성 후 car2와 연결

        car2.brand = "페라리";  // car2 객체의 brand 값 저장
        car2.color = "노랑";    // car2 객체의 color 값 저장
        car2.speed = 150;      // car2 객체의 speed 값 저장

        car1.drive();          // 첫 번째 객체의 drive() 호출
        car1.printInfo();      // 첫 번째 객체 정보 출력

        car2.drive();          // 두 번째 객체의 drive() 호출
        car2.printInfo();      // 두 번째 객체 정보 출력
    }

    // 출력결과
    // 포르쉐 자동차가 출발합니다.
    // 브랜드: 포르쉐, 색상: 빨강, 속도: 120
    // 페라리 자동차가 출발합니다.
    // 브랜드: 페라리, 색상: 노랑, 속도: 150
}

이 코드는 같은 Car 클래스로 객체를 두 개 만들고,
각 객체에 서로 다른 값을 넣어 사용한 예제다.

여기서 봐야 할 핵심은
같은 틀로 만들었어도, 객체마다 저장된 값은 서로 다를 수 있다는 점이다.

즉,

  • car1은 포르쉐 정보를 가진 객체
  • car2는 페라리 정보를 가진 객체

로 따로 존재한다.



헷갈리기 쉬운 부분

객체를 println()으로 그냥 출력하면, 멤버변수 값이 바로 예쁘게 나오지 않는다.

예를 들어

System.out.println(car1);

처럼 출력하면 보통 클래스이름@어떤값 형태가 나온다.
이건 브랜드나 색상이 자동으로 출력된 것이 아니라,
객체 자체를 기본 형태로 보여준 것이다.

또 참조변수는 숫자처럼 값을 직접 담는 변수로 생각하면 헷갈린다.
여기서는

“이 변수가 어떤 객체를 가리키고 있다”

이 감각을 먼저 잡는 것이 중요하다.

즉, car1 안에 자동차가 통째로 들어 있다고 보기보다,
car1이 자동차 객체를 찾아갈 수 있게 해 주는 이름표라고 이해하면 된다.



같은 객체를 여러 변수가 가리킬 수 있다


참조변수 하나는 한 번에 하나의 객체만 가리킬 수 있다.
하지만 여러 참조변수가 같은 객체를 함께 가리키는 것은 가능하다.

예제: CarTest4

class Car {
    String brand;

    void drive() {
        System.out.println(brand + " 자동차가 출발합니다.");
    }
}

public class CarTest4 {
    public static void main(String[] args) {
        Car car1 = new Car();
        car1.brand = "포르쉐";

        Car car2 = new Car();
        car2.brand = "페라리";

        car2 = car1;

        car1.drive();
        car2.drive();
    }

    // 출력결과
    // 포르쉐 자동차가 출발합니다.
    // 포르쉐 자동차가 출발합니다.
}

처음에는

  • car1 → 포르쉐 객체
  • car2 → 페라리 객체

를 각각 가리킨다.

그런데

car2 = car1;

이 코드가 실행되면, car2는 더 이상 원래의 페라리 객체를 보지 않고
car1이 가리키는 포르쉐 객체를 같이 가리키게 된다.

그래서 그 뒤에는

  • car1.drive()
  • car2.drive()
    둘 다 같은 포르쉐 객체의 drive()를 호출하게 되고,
    결과도 똑같이 나온다.

    여기서 중요한 것은
    값이 복사된 것이 아니라, 가리키는 대상이 바뀌었다는 점이다.

    즉, car2 = car1;은
    포르쉐 자동차를 하나 더 만든 것이 아니라,
    car2라는 이름표도 같은 자동차를 보게 만든 것이다.



5. 객체배열

개념

객체를 하나만 만들 때는 참조변수 하나로도 충분하다.
예를 들어 Car car1 = new Car();처럼 만들면 Car 객체 하나를 사용할 수 있다.
하지만 같은 클래스의 객체를 여러 개 만들어야 할 때는 car1, car2, car3처럼 참조변수를 계속 따로 만드는 방식이 점점 불편해진다.
이럴 때 사용하는 것이 객체배열이다.

객체배열은 같은 클래스의 객체들을 한꺼번에 관리하기 위해 참조변수들을 배열로 묶어 놓은 것이라고 보면 된다.
즉, 객체배열 안에는 객체 자체가 들어가는 것이 아니라 각 객체를 가리키는 참조값이 저장된다.



객체배열 문법

객체배열은 먼저 아래처럼 만든다.

Car[] cars = new Car[3];

이 문장은 다음 뜻이다.

  • Car[] cars
    → Car 객체를 가리킬 수 있는 참조변수 배열 선언
    (Car는 자동차 객체를 만들기 위한 클래스 이름이다.
    Car[] cars는 그 Car 타입의 객체들을 가리킬 수 있는 참조값을 배열로 관리하는 선언이다.)

  • new Car[3]
    → Car 객체의 참조값을 3개 저장할 수 있는 배열 생성
    (객체 3개를 만드는 것이 아니라, 객체를 넣을 자리 3칸을 만드는 것이다.)

즉, 이 코드는 Car 객체 3개를 만든 코드가 아니라, Car 객체를 넣을 자리 3칸을 만든 코드다.
그래서 객체배열을 사용할 때는 보통 아래 순서로 진행한다.
1. 객체배열을 만든다.
2. 배열의 각 칸에 실제 객체를 생성해서 넣는다.
3. 배열에 저장된 객체를 꺼내 사용한다.

예를 들면 이렇게 된다.

Car[] cars = new Car[3]; // 1. 객체를 넣을 배열 생성

cars[0] = new Car();     // 2. 0번 칸에 실제 객체 생성 후 저장
cars[1] = new Car();     // 2. 1번 칸에 실제 객체 생성 후 저장
cars[2] = new Car();     // 2. 2번 칸에 실제 객체 생성 후 저장

cars[0].brand = "포르쉐"; // 3. 배열에 들어 있는 객체 사용

즉,

  • new Car[3] → 배열 생성
  • new Car() → 실제 객체 생성

이 둘은 전혀 다른 의미다.



핵심 특징

  • 같은 클래스 객체를 여러 개 관리할 때 사용한다.
  • 배열 안에는 객체 자체가 아니라 객체를 가리키는 참조값이 저장된다.
  • 객체배열을 만들었다고 해서 객체까지 자동으로 생성되지는 않는다.
  • 먼저 배열을 만들고, 그다음 각 칸에 객체를 따로 생성해서 넣어야 한다.
  • 객체배열도 배열이므로 인덱스로 각 객체에 접근한다.
  • 반복문과 함께 사용하면 여러 객체를 한 번에 처리하기 좋다.

코드 예제

예제: CarTest5

class Car {
    String brand;
    String color;
    int speed;

    void printInfo() {
        System.out.println("브랜드: " + brand + ", 색상: " + color + ", 속도: " + speed);
    }
}

public class CarTest5 {
    public static void main(String[] args) {
        Car[] cars = new Car[3];   // Car 객체 참조값 3개를 저장할 수 있는 배열 생성

        cars[0] = new Car();       // 0번 칸에 실제 Car 객체 생성 후 저장
        cars[0].brand = "포르쉐";   // 첫 번째 객체의 brand 값 저장
        cars[0].color = "빨강";     // 첫 번째 객체의 color 값 저장
        cars[0].speed = 120;       // 첫 번째 객체의 speed 값 저장

        cars[1] = new Car();       // 1번 칸에 실제 Car 객체 생성 후 저장
        cars[1].brand = "페라리";   // 두 번째 객체의 brand 값 저장
        cars[1].color = "노랑";     // 두 번째 객체의 color 값 저장
        cars[1].speed = 150;       // 두 번째 객체의 speed 값 저장

        cars[2] = new Car();       // 2번 칸에 실제 Car 객체 생성 후 저장
        cars[2].brand = "람보르기니"; // 세 번째 객체의 brand 값 저장
        cars[2].color = "검정";     // 세 번째 객체의 color 값 저장
        cars[2].speed = 180;       // 세 번째 객체의 speed 값 저장

        for (int i = 0; i < cars.length; i++) { // 배열의 각 칸에 저장된 객체를 하나씩 꺼냄
            cars[i].printInfo();                // 꺼낸 객체의 printInfo() 호출
        }
    }

    // 출력결과
    // 브랜드: 포르쉐, 색상: 빨강, 속도: 120
    // 브랜드: 페라리, 색상: 노랑, 속도: 150
    // 브랜드: 람보르기니, 색상: 검정, 속도: 180
}

이 코드는 객체배열을 사용하는 가장 기본적인 흐름을 그대로 보여준다.
먼저 Car[] cars = new Car[3];으로 객체를 넣을 배열을 만들고,
그다음 cars[0] = new Car();처럼 각 칸에 실제 객체를 생성해서 넣는다.

그 후 각 객체에 값을 저장하고,
마지막에는 반복문으로 배열 안의 객체를 하나씩 꺼내 메서드를 호출한다.
즉, 객체배열은 여러 객체를 한 번에 관리하기 위해 배열에 넣어 두고, 필요할 때 하나씩 꺼내 사용하는 방식이라고 이해하면 된다.

헷갈리기 쉬운 부분

가장 많이 헷갈리는 부분은 아래 두 코드의 차이다.

Car[] cars = new Car[3];

이 코드는 Car 객체 3개를 만든 것이 아니다.
이 코드는 Car 객체를 가리킬 참조값을 저장할 수 있는 배열만 만든 것이다.
(즉, Car는 클래스이고, Car[]는 그 Car 타입을 여러 개 관리하기 위한 배열이다.)


반면 아래 코드는 실제 객체를 만드는 코드다.

cars[0] = new Car();

즉,

  • new Car[3] → 참조값 3개를 담을 배열 생성
    (객체가 들어갈 자리만 만들어짐)

  • new Car() → 실제 Car 객체 생성
    (배열의 한 칸이 가리킬 실제 대상이 만들어짐)

이라고 구분해야 한다.


이걸 헷갈리면 배열만 만들어 놓고 바로 아래처럼 쓰게 된다.

cars[0].brand = "포르쉐";

하지만 이건 아직 cars[0]에 실제 객체가 들어 있지 않다면 에러가 난다.
왜냐하면 배열의 0번 칸은 만들어졌지만, 그 칸이 가리킬 실제 객체는 아직 생성하지 않았기 때문이다.
즉, 배열 칸은 있는데 그 안에 연결된 Car 객체는 아직 없는 상태라고 보면 된다.


그래서 객체배열은 항상 아래 순서로 기억하면 된다.
1. 배열 생성
(Car[] cars = new Car[3];)

  1. 각 칸에 객체 생성 후 저장
    (cars[0] = new Car();)

  2. 객체의 변수나 메서드 사용
    (cars[0].brand = "포르쉐";)




6. 생성자

개념

객체는 만들기만 하면 끝이 아니다.
보통은 객체를 만들 때부터 필요한 값을 함께 넣고 시작하는 경우가 많다.

예를 들어 자동차 객체를 만든다면,

  • 브랜드는 무엇인지
  • 색상은 무엇인지
  • 속도는 얼마인지

같은 값을 처음부터 넣고 싶을 수 있다.

이럴 때 사용하는 것이 생성자다.

생성자는
객체를 만들 때 처음 값을 넣어 주는 역할을 한다고 이해하면 쉽다.

즉, 객체를 만든 뒤에 값을 하나씩 따로 넣을 수도 있지만,
생성자를 사용하면 객체를 만드는 순간 필요한 값을 함께 넣을 수 있다.

문법은 아래와 같다.

클래스명(매개변수) {
    // 객체가 만들어질 때 할 작업
}

생성자는 클래스 이름과 같은 이름을 사용하고,
일반 메서드와 달리 반환형을 쓰지 않는다.





핵심 특징

  • 객체를 만들 때 함께 실행된다.
  • 객체를 만들면서 필요한 값을 넣을 수 있다.
  • 주로 멤버변수에 처음 값을 넣을 때 사용한다.
  • 이름은 클래스명과 같아야 한다.
  • 반환형을 적지 않는다.



코드 예제

예제: CarTest6

class Car {
    String brand;
    String color;
    int speed;

    Car(String brand, String color, int speed) { // 객체 생성 시 전달받은 값을 저장하는 생성자
        this.brand = brand; // 전달받은 brand 값을 현재 객체의 brand에 저장
        this.color = color; // 전달받은 color 값을 현재 객체의 color에 저장
        this.speed = speed; // 전달받은 speed 값을 현재 객체의 speed에 저장
    }

    void printInfo() { // 객체에 저장된 값을 출력하는 메서드
        System.out.println("브랜드: " + brand + ", 색상: " + color + ", 속도: " + speed);
    }
}

public class CarTest6 {
    public static void main(String[] args) {
        Car car1 = new Car("포르쉐", "빨강", 120);
        // 1. new Car(...)로 객체 생성
        // 2. "포르쉐", "빨강", 120 값이 생성자로 전달됨
        // 3. 생성자에서 각 멤버변수 brand, color, speed에 저장됨

        Car car2 = new Car("페라리", "노랑", 150);
        // 1. 두 번째 Car 객체 생성
        // 2. "페라리", "노랑", 150 값이 생성자로 전달됨
        // 3. 생성자에서 각 멤버변수에 저장됨

        car1.printInfo(); // car1 객체에 저장된 값 출력
        car2.printInfo(); // car2 객체에 저장된 값 출력
    }

    // 출력결과
    // 브랜드: 포르쉐, 색상: 빨강, 속도: 120
    // 브랜드: 페라리, 색상: 노랑, 속도: 150
}

이 코드는 자동차 객체를 만들면서
브랜드, 색상, 속도를 한 번에 넣는 예제다.

예를 들어

Car car1 = new Car("포르쉐", "빨강", 120);

이 한 줄은

  • Car 객체를 만들고
  • 동시에 브랜드, 색상, 속도 값을 넣는 것

까지 한 번에 처리한다.

즉, 생성자는
객체를 만들면서 필요한 시작값도 같이 준비하게 해 주는 문법이라고 보면 된다.



this

생성자 안에서는 매개변수 이름과 멤버변수 이름이 같아지는 경우가 많다.

Car(String brand, String color, int speed) {
    this.brand = brand;  // 왼쪽 this.brand는 멤버변수, 오른쪽 brand는 매개변수
    this.color = color;
    this.speed = speed;
}

여기서 어렵게 생각하지 말고 이렇게 보면 된다.

  • 오른쪽 brand, color, speed → 바깥에서 전달받은 값 (매개변수)
  • 왼쪽 this.brand, this.color, this.speed → 지금 만들고 있는 객체의 변수 (멤버변수)

즉,

this.brand = brand;

는
전달받은 브랜드 값을, 지금 만들고 있는 자동차 객체의 brand에 넣는다는 뜻이다.

여기서 this는
지금 만들고 있는 객체 자신이라고 이해하면 된다.



기본 생성자와 생성자를 여러 개 만드는 경우

생성자는 하나만 만드는 것이 아니다.
필요에 따라 여러 개 만들 수 있다.

예를 들어

  • 아무 값 없이 기본 자동차를 만들 수도 있고
  • 원하는 브랜드와 색상을 직접 넣어서 만들 수도 있다

이렇게 상황이 다를 수 있다.

그래서 생성자를 여러 개 만들어 둘 수 있다.

예제: CarTest7

class Car {
    String brand;
    String color;
    int speed;

    Car() { // 매개변수가 없는 기본 생성자
        brand = "기본자동차"; // brand에 기본값 저장
        color = "흰색";      // color에 기본값 저장
        speed = 0;           // speed에 기본값 저장
    }

    Car(String brand, String color, int speed) { // 값을 직접 받아 저장하는 생성자
        this.brand = brand; // 전달받은 brand 값을 현재 객체의 brand에 저장
        this.color = color; // 전달받은 color 값을 현재 객체의 color에 저장
        this.speed = speed; // 전달받은 speed 값을 현재 객체의 speed에 저장
    }

    void printInfo() { // 객체에 저장된 값을 출력하는 메서드
        System.out.println("브랜드: " + brand + ", 색상: " + color + ", 속도: " + speed);
    }
}

public class CarTest7 {
    public static void main(String[] args) {
        Car car1 = new Car();
        // 1. new Car()로 객체 생성
        // 2. 기본 생성자가 자동 호출됨
        // 3. 생성자 안에서 기본값 "기본자동차", "흰색", 0 이 저장됨

        Car car2 = new Car("포르쉐", "빨강", 120);
        // 1. new Car(...)로 객체 생성
        // 2. 전달한 값이 매개변수 있는 생성자로 들어감
        // 3. 생성자 안에서 각 멤버변수에 저장됨

        car1.printInfo(); // 기본 생성자로 만들어진 car1의 값 출력
        car2.printInfo(); // 매개변수 생성자로 만들어진 car2의 값 출력
    }

    // 출력결과
    // 브랜드: 기본자동차, 색상: 흰색, 속도: 0
    // 브랜드: 포르쉐, 색상: 빨강, 속도: 120
}

여기서는 생성자가 두 개 있다.

  • Car() → 기본값으로 자동차를 만들 때 사용
  • Car(String brand, String color, int speed) → 원하는 값을 직접 넣을 때 사용

즉, 같은 자동차 클래스라도
객체를 만드는 방법은 여러 가지로 준비할 수 있다는 뜻이다.

이렇게 매개변수가 다른 생성자를 여러 개 두는 것을 오버로딩이라고 한다.



헷갈리기 쉬운 부분

생성자는 메서드처럼 생겼지만, 일반 메서드처럼 따로 호출하는 것이 아니다.
보통은 객체를 만들 때 new와 함께 실행된다.

예를 들어

new Car("포르쉐", "빨강", 120);

이렇게 객체를 만들면 생성자도 같이 실행된다.

또 생성자에는 void를 붙이지 않는다.
void Car(...)처럼 쓰면 생성자가 아니라 일반 메서드가 된다.

그리고 기본 생성자는 항상 자동으로 생기는 것이 아니다.

  • 클래스에 생성자를 하나도 만들지 않으면 기본 생성자가 자동으로 들어갈 수 있다.
  • 하지만 생성자를 하나라도 직접 만들면, 필요한 생성자는 직접 작성해야 한다.

즉, 생성자를 직접 만들기 시작하면
필요한 형태는 스스로 챙겨야 한다.




7. 멤버변수와 지역변수

개념

멤버변수는 클래스 안에서, 메서드 밖에 선언한 변수다.
지역변수는 메서드 안에서 선언한 변수다.

즉,

  • 클래스 안, 메서드 밖 → 멤버변수
  • 메서드 안 → 지역변수

다.



핵심 특징

  • 멤버변수는 객체의 정보를 저장한다.
  • 지역변수는 메서드 안에서 잠깐 사용하는 값이다.
  • 객체의 속성은 보통 멤버변수로 만든다.



코드 예제

예제: CarTest8

class Car {
    String brand;   // 멤버변수
    int speed;      // 멤버변수

    void printInfo() {
        String message = "자동차 정보 출력";  // 지역변수
        System.out.println(message);
        System.out.println("브랜드: " + brand + ", 속도: " + speed);
    }
}

public class CarTest8 {
    public static void main(String[] args) {
        Car car1 = new Car();
        car1.brand = "포르쉐";
        car1.speed = 120;
        car1.printInfo();
    }

    // 출력결과
    // 자동차 정보 출력
    // 브랜드: 포르쉐, 속도: 120
}

여기서

  • brand, speed는 멤버변수
  • message는 지역변수

다.



헷갈리기 쉬운 부분

멤버변수는 값을 넣지 않아도 기본값이 들어갈 수 있지만,
지역변수는 값을 넣지 않고 바로 사용할 수 없다.

예를 들어 참조형 멤버변수는 값을 넣지 않으면 null이 들어갈 수 있다.



예제: CarTest9

class Car {
    String brand;
    String color;

    void printInfo() {
        System.out.println("브랜드: " + brand + ", 색상: " + color);
    }
}

public class CarTest9 {
    public static void main(String[] args) {
        Car car1 = new Car();
        car1.brand = "포르쉐";

        car1.printInfo();
    }

    // 출력결과
    // 브랜드: 포르쉐, 색상: null
}

여기서는 color에 값을 넣지 않았기 때문에 null이 나온다.

즉, 멤버변수는 기본값이 들어가서 코드가 실행될 수 있지만,
그 값이 의도한 값은 아닐 수 있다는 점도 함께 봐야 한다.




8. 객체 간의 상호작용

개념

객체지향에서는 객체가 혼자만 존재하는 것이 아니라,
필요할 때 다른 객체의 기능을 사용한다.

즉, 객체끼리는 보통 메서드 호출을 통해 연결된다.

지금 단계에서는 단순하게 이해하면 된다.

  • 다른 객체를 사용하려면 그 객체를 가리키는 변수가 있어야 한다.
  • 그 객체의 메서드를 .으로 호출하면 된다.



핵심 특징

  • 객체는 혼자만 동작하지 않고 서로 기능을 주고받을 수 있다.
  • 다른 객체를 사용한다는 것은 결국 그 객체의 메서드를 활용하는 것이다.
  • 한 객체가 직접 모든 일을 다 하는 것이 아니라, 필요한 일을 다른 객체에게 맡길 수도 있다.

코드 예제

예제: CarTest10

class Car {
    String brand;

    void drive() {
        System.out.println(brand + " 자동차가 출발합니다.");
    }
}

class Driver {
    String name;

    void driveCar(Car car) {   // Driver 객체가 Car 객체를 받아서 사용
        System.out.println(name + "이(가) 운전을 시작합니다.");
        car.drive();           // 전달받은 Car 객체의 메서드 호출
    }
}

public class CarTest10 {
    public static void main(String[] args) {
        Car car1 = new Car();      // Car 객체 생성
        car1.brand = "포르쉐";      // Car 객체의 brand 값 저장

        Driver driver1 = new Driver(); // Driver 객체 생성
        driver1.name = "김운전자";      // Driver 객체의 name 값 저장

        driver1.driveCar(car1);    // Driver 객체가 Car 객체를 받아 사용
    }

    // 출력결과
    // 김운전자가 운전을 시작합니다.
    // 포르쉐 자동차가 출발합니다.
}

이 코드는 Driver 객체와 Car 객체가 서로 어떻게 연결되는지 보여준다.

여기서 중요한 흐름은 이렇다.
Car 객체는 자동차의 기능인 drive()를 가지고 있다.
Driver 객체는 driveCar() 메서드 안에서 Car 객체를 전달받는다.
그리고 전달받은 Car 객체의 drive()를 호출한다.


즉, 운전자 객체가 자동차 객체를 직접 만들어 내는 것이 아니라,
이미 만들어진 자동차 객체의 기능을 가져다 쓰는 방식이다.

이렇게 보면 객체 간의 상호작용은
한 객체가 다른 객체의 기능을 호출해서 함께 동작하는 것이라고 이해하면 된다.



헷갈리기 쉬운 부분

객체지향의 핵심은 객체를 많이 만드는 것이 아니다.
핵심은 필요한 대상을 나누고, 각 대상이 자기 역할을 하게 만드는 것이다.

예를 들어 자동차 객체가 있고 운전자 객체가 있다면,
운전자가 자동차의 메서드를 호출해서 자동차를 움직이게 할 수 있다.

이렇게 보면 객체지향은
대상을 나누고, 그 대상들이 서로 협력하게 만드는 방식이라고도 볼 수 있다.




참고

이번 파트에서는 아래 흐름만 정확히 잡으면 된다.

  • 객체지향은 대상을 중심으로 생각하는 방식이다.
  • 자바에서는 그 대상을 만들기 위해 먼저 클래스를 만든다.
  • 객체는 클래스로 실제 만든 대상이다.
  • 객체 안에는 멤버변수와 메서드가 들어간다.
  • 객체는 new로 만들고 .으로 사용한다.
  • 생성자는 객체를 만들 때 호출되어 초기화를 맡는다.

이 흐름이 잡히면 뒤에서 배우는 상속, 클래스 변수, 클래스 메서드도 훨씬 쉽게 이어진다.

0개의 댓글