Skip to main content

객체지향 프로그래밍 입문: 클래스와 객체

지금까지는 변수, 조건문, 반복문, 메서드, 배열, 문자열을 배우며 프로그램을 만드는 기본 도구를 익혔다. 이제부터는 Java를 좀 더 Java답게 쓰는 출발점으로 들어간다. 바로 객체지향 프로그래밍이다.

처음 객체지향을 만나면 조금 낯설 수 있다. 변수는 알겠고, 메서드도 알겠는데 왜 굳이 클래스와 객체라는 새로운 개념이 필요한지 의문이 들기 때문이다. 하지만 한 번 감을 잡으면 생각보다 자연스럽다. 현실의 대상을 프로그램 속에 옮겨 담는 방식이라고 생각하면 된다. 학생, 자동차, 은행 계좌, 상품, 게시글 같은 것들을 각각의 특징과 행동을 가진 존재로 다루는 것이다.

이번 장에서는 클래스, 객체, 필드, 메서드, 생성자, 접근 제어자를 차근차근 살펴보며 객체지향의 첫 감각을 잡아 보겠다.

객체지향 프로그래밍 입문: 클래스와 객체

객체지향 프로그래밍은 왜 필요할까

작은 프로그램은 변수와 메서드만으로도 충분히 만들 수 있다. 하지만 프로그램이 커지면 데이터와 기능이 흩어지기 시작한다. 예를 들어 학생 정보를 다룬다고 해 보자. 이름, 나이, 학번 같은 데이터가 있고, 공부하기, 자기소개하기, 학점 계산하기 같은 기능도 있다. 이 정보와 동작이 여기저기 퍼져 있으면 코드가 읽기 어렵고 수정도 힘들어진다.

객체지향 프로그래밍은 이런 문제를 줄이기 위해 관련 있는 데이터와 기능을 하나로 묶는 방식을 사용한다. 즉, 학생에 대한 정보와 학생이 할 수 있는 행동을 Student라는 하나의 틀 안에 담는 것이다.

이 방식의 장점은 분명하다.

  • 코드를 역할별로 나누기 쉬워진다.

  • 재사용하기 편해진다.

  • 수정할 때 영향 범위를 파악하기 쉬워진다.

  • 현실 세계의 개념과 연결해서 생각하기 좋다.

한마디로 말하면, 객체지향은 코드를 더 길게 만들기 위한 장식이 아니라 복잡한 프로그램을 다루기 위한 정리 기술이다.

클래스와 객체를 한 번에 이해하기

객체지향의 핵심은 클래스와 객체다.

클래스는 객체를 만들기 위한 설계도다. 객체는 그 설계도로 실제로 만들어진 대상이다. 붕어빵 틀과 붕어빵의 관계를 많이 비유로 드는데, 아주 틀린 비유는 아니지만 너무 오래 붙잡고 있을 필요는 없다. 더 중요한 것은 다음 문장이다.

클래스는 공통 구조를 정의하고, 객체는 그 구조를 바탕으로 메모리에 만들어진 실제 데이터다.

예를 들어 Car 클래스가 있다고 하자. 자동차가 공통으로 가지는 정보는 색상, 모델명, 현재 속도일 수 있다. 자동차가 공통으로 하는 행동은 출발하기, 가속하기, 멈추기일 수 있다. 이런 공통 구조를 클래스에 적는다.

그리고 실제 자동차 객체를 만들면, 빨간 스포츠카도 만들 수 있고, 파란 세단도 만들 수 있다. 둘 다 같은 Car 클래스로 만들었지만 상태는 서로 다를 수 있다.

public class Car {
    String model;
    String color;
    int speed;
}

위 코드는 자동차의 설계도다. 아직 자동차가 실제로 만들어진 것은 아니다. 실제 객체는 이렇게 만든다.

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

        car1.model = "Sedan";
        car1.color = "Black";
        car1.speed = 0;

        car2.model = "Sports";
        car2.color = "Red";
        car2.speed = 0;
    }
}

new Car()는 Car 클래스를 바탕으로 새로운 객체를 만드는 표현이다. car1과 car2는 같은 클래스에서 만들어졌지만 서로 다른 객체다. 즉, 별개의 존재다.

필드: 객체가 가지고 있는 값

클래스 안에 선언된 변수 중에서 객체의 상태를 나타내는 것을 필드라고 한다. 쉽게 말해 객체가 들고 있는 데이터다.

아까 본 model, color, speed가 모두 필드다.

public class Car {
    String model;
    String color;
    int speed;
}

각 객체는 자기만의 필드 값을 가진다. 그래서 car1.speed와 car2.speed는 서로 다른 값을 가질 수 있다. 같은 틀에서 만들어졌다고 해서 값까지 똑같아야 하는 것은 아니다.

필드를 볼 때는 이렇게 생각하면 이해가 쉽다.

  • 클래스는 어떤 정보를 가질지 정한다.

  • 객체는 그 정보를 실제 값으로 채운다.

  • 필드는 객체의 현재 상태를 보여 준다.

예를 들어 속도가 0이면 멈춘 상태이고, 80이면 달리는 상태다. 즉, 필드는 객체의 "지금 모습"을 담고 있다.

메서드: 객체가 할 수 있는 행동

객체가 값만 들고 있으면 조금 심심하다. 자동차라면 달릴 수도 있어야 하고 멈출 수도 있어야 한다. 객체가 수행하는 동작을 메서드로 표현한다.

public class Car {
    String model;
    String color;
    int speed;

    void accelerate() {
        speed += 10;
    }

    void brake() {
        if (speed >= 10) {
            speed -= 10;
        }
    }

    void showInfo() {
        System.out.println("모델: " + model);
        System.out.println("색상: " + color);
        System.out.println("속도: " + speed);
    }
}

이제 Car는 단순한 데이터 묶음이 아니다. 스스로 가속하고, 감속하고, 자기 정보를 출력할 수 있다.

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.model = "Sedan";
        car.color = "Blue";

        car.accelerate();
        car.accelerate();
        car.showInfo();
    }
}

메서드를 클래스 안에 함께 두면 코드가 훨씬 자연스러워진다. 자동차의 속도를 바꾸는 일은 자동차와 관련된 행동이므로 Car 안에 넣는 것이 어울린다. 이것이 객체지향이 주는 중요한 감각이다.

데이터와 기능이 멀리 떨어져 있지 않고, 서로 관련된 것끼리 붙어 있는 구조가 된다.

클래스 안의 메서드와 지금까지 배운 메서드는 무엇이 다를까

사실 문법적으로 메서드는 이미 배운 내용과 크게 다르지 않다. 매개변수를 받을 수 있고, 반환값을 줄 수도 있다. 다만 이제는 메서드가 특정 객체와 연결되어 동작한다는 점이 중요하다.

예를 들어 다음 메서드는 자동차의 속도를 바꾼다.

void accelerate() {
    speed += 10;
}

이 메서드는 별도의 speed 값을 전달받지 않는다. 그 대신 이 메서드를 호출한 객체 자신의 필드를 사용한다. car1.accelerate()를 호출하면 car1의 speed가 바뀌고, car2.accelerate()를 호출하면 car2의 speed가 바뀐다.

같은 메서드 정의를 공유하지만, 실제로 다루는 값은 객체마다 다르다. 이 점이 객체지향 메서드의 재미있는 부분이다.

객체를 만드는 순간: 생성자

객체를 만들고 나서 필드 값을 하나씩 넣어도 되지만, 매번 그렇게 하면 빠뜨리는 값이 생기기 쉽다. 자동차를 만들었는데 모델명을 빼먹고, 학생 객체를 만들었는데 학번을 안 넣는 식이다. 이런 실수를 줄이기 위해 생성자를 사용한다.

생성자는 객체가 만들어질 때 실행되는 특별한 메서드다. 이름이 클래스 이름과 같고, 반환형을 쓰지 않는다.

public class Car {
    String model;
    String color;
    int speed;

    Car(String model, String color) {
        this.model = model;
        this.color = color;
        this.speed = 0;
    }

    void showInfo() {
        System.out.println("모델: " + model);
        System.out.println("색상: " + color);
        System.out.println("속도: " + speed);
    }
}

이제 객체를 만들 때 필요한 값을 함께 넘길 수 있다.

public class Main {
    public static void main(String[] args) {
        Car car = new Car("SUV", "White");
        car.showInfo();
    }
}

이 방식의 장점은 객체가 처음부터 의미 있는 상태로 만들어진다는 점이다. 만들자마자 사용할 수 있는 객체가 되는 것이다.

기본 생성자란 무엇인가

생성자를 하나도 작성하지 않으면 Java는 자동으로 기본 생성자를 넣어 준다.

Car() {
}

이런 형태라고 생각하면 된다. 하지만 생성자를 하나라도 직접 만들면, Java가 자동으로 기본 생성자를 넣어 주지 않는다. 그래서 아래처럼 매개변수가 있는 생성자만 만들었는데 new Car()를 호출하면 오류가 난다.

Car(String model, String color) {
    this.model = model;
    this.color = color;
}

필요하다면 기본 생성자도 직접 만들어야 한다.

Car() {
}

Car(String model, String color) {
    this.model = model;
    this.color = color;
}

처음에는 이 규칙 때문에 종종 헷갈린다. 하지만 익숙해지면 "객체를 어떤 방식으로 만들게 할 것인가"를 설계하는 감각으로 이해할 수 있다.

this: 지금 이 객체를 가리키는 참조

생성자를 설명할 때 this.model = model; 같은 코드를 봤다. 여기서 this는 현재 객체 자신을 가리킨다.

public class Car {
    String model;

    Car(String model) {
        this.model = model;
    }
}

위 코드에서 왼쪽의 this.model은 필드이고, 오른쪽의 model은 매개변수다. 이름이 같기 때문에 그냥 model = model;이라고 쓰면 둘을 구별할 수 없다. 그래서 현재 객체의 필드라는 뜻으로 this.model이라고 적는다.

this는 생성자에서만 쓰는 것이 아니다. 메서드 안에서도 현재 객체의 필드나 메서드를 분명하게 가리키고 싶을 때 사용할 수 있다.

void setSpeed(int speed) {
    this.speed = speed;
}

처음에는 this가 조금 낯설지만, "지금 이 객체"라고 번역하면 대부분의 상황이 이해된다.

접근 제어자: 어디까지 보여 줄 것인가

객체지향에서 중요한 또 하나의 개념은 정보를 함부로 다 드러내지 않는 것이다. 객체 안의 값이 아무 데서나 마구 바뀌면 예상하지 못한 문제가 생긴다. 그래서 Java는 접근 범위를 조절하는 장치를 제공한다. 이것이 접근 제어자다.

가장 먼저 알아둘 것은 public과 private이다.

  • public: 어디서나 접근 가능

  • private: 해당 클래스 내부에서만 접근 가능

예를 들어 은행 계좌를 생각해 보자. 잔액은 아무 코드에서나 마음대로 바꾸게 두면 위험하다.

public class BankAccount {
    private String owner;
    private int balance;

    BankAccount(String owner, int balance) {
        this.owner = owner;
        this.balance = balance;
    }

    void deposit(int amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    void withdraw(int amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        }
    }

    void showBalance() {
        System.out.println(owner + "의 잔액: " + balance);
    }
}

이렇게 만들면 외부에서 balance를 직접 바꾸지 못한다.

public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount("김자바", 10000);
        account.deposit(5000);
        account.withdraw(3000);
        account.showBalance();
    }
}

만약 balance가 public이었다면 누군가 account.balance = -999999; 같은 코드를 써 버릴지도 모른다. 프로그램 입장에서는 그야말로 재난 영화의 시작이다.

접근 제어자는 객체를 단순히 숨기기 위한 장치가 아니다. 객체가 자기 상태를 올바르게 유지하도록 보호하는 장치다.

getter와 setter: 안전하게 읽고 바꾸기

필드를 private으로 막아 두면 외부에서 값을 읽거나 바꿀 방법이 필요할 때가 있다. 이때 사용하는 메서드가 흔히 말하는 getter와 setter다.

  • getter: 값을 읽어 오는 메서드

  • setter: 값을 바꾸는 메서드

예를 들어 학생 정보를 다루는 클래스를 보자.

public class Student {
    private String name;
    private int age;

    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
}

이렇게 하면 나이를 변경할 때 조건을 걸 수 있다. 나이가 0 이하인 값은 막아 버릴 수 있는 것이다.

여기서 중요한 점은 모든 필드에 무조건 getter와 setter를 만드는 것이 정답은 아니라는 것이다. 정말 필요한 것만 열어 두는 습관이 좋다. 값을 읽는 것은 허용하되 바꾸는 것은 막고 싶을 수도 있다. 예를 들어 주민등록번호, 계좌번호, 생성일 같은 값은 한 번 정해지면 바뀌지 않게 설계할 수 있다.

즉, 접근 제어와 getter/setter는 문법 암기가 아니라 객체의 규칙을 설계하는 일이다.

좋은 객체는 자기 일을 스스로 한다

객체지향을 배울 때 흔히 하는 실수는 클래스를 단순한 데이터 창고처럼 사용하는 것이다. 필드만 잔뜩 만들고, 실제 로직은 전부 Main이나 다른 클래스에 몰아 넣는 방식이다.

예를 들어 아래 코드는 조금 아쉽다.

public class Player {
    String name;
    int hp;
}
public class Main {
    public static void main(String[] args) {
        Player p = new Player();
        p.name = "용사";
        p.hp = 100;

        p.hp -= 10;
        p.hp -= 20;
        System.out.println(p.name + "의 체력: " + p.hp);
    }
}

이 코드는 돌아가긴 하지만, 체력을 깎는 규칙이 객체 바깥에 흩어져 있다. 나중에 체력은 0 아래로 내려가면 안 된다는 규칙이 생기면, 관련 코드를 모두 찾아 고쳐야 한다.

조금 더 객체지향적으로 바꾸면 다음과 같다.

public class Player {
    String name;
    int hp;

    Player(String name, int hp) {
        this.name = name;
        this.hp = hp;
    }

    void takeDamage(int damage) {
        hp -= damage;
        if (hp < 0) {
            hp = 0;
        }
    }

    void showStatus() {
        System.out.println(name + "의 체력: " + hp);
    }
}
public class Main {
    public static void main(String[] args) {
        Player p = new Player("용사", 100);
        p.takeDamage(10);
        p.takeDamage(20);
        p.showStatus();
    }
}

이제 체력 처리 규칙은 Player 안에 있다. 객체가 자기 데이터를 스스로 관리한다. 이 감각이 중요하다.

객체지향적으로 생각한다는 것은 종종 이런 질문으로 시작된다.

"이 일은 누구의 책임일까?"

자동차의 속도 변경은 자동차의 책임이고, 계좌의 입금과 출금은 계좌의 책임이며, 플레이어의 체력 관리는 플레이어의 책임이다. 이런 식으로 역할을 나누면 코드가 훨씬 읽기 좋아진다.

예제로 익히는 클래스 설계: 학생 관리 클래스 만들기

지금까지 배운 개념을 한 번에 묶어 보자. 학생 한 명의 정보를 다루는 클래스를 만들어 보겠다.

public class Student {
    private String name;
    private int grade;
    private int score;

    public Student(String name, int grade) {
        this.name = name;
        this.grade = grade;
        this.score = 0;
    }

    public void study(int hours) {
        if (hours > 0) {
            score += hours * 5;
            if (score > 100) {
                score = 100;
            }
        }
    }

    public void introduce() {
        System.out.println("안녕하세요. 저는 " + grade + "학년 " + name + "입니다.");
    }

    public int getScore() {
        return score;
    }

    public String getName() {
        return name;
    }
}

사용하는 쪽 코드는 이렇게 된다.

public class Main {
    public static void main(String[] args) {
        Student student = new Student("이자바", 2);

        student.introduce();
        student.study(3);

        System.out.println(student.getName() + "의 점수: " + student.getScore());
    }
}

이 예제에는 객체지향의 기초가 여러 개 들어 있다. 학생의 이름, 학년, 점수는 필드다. 공부하기와 자기소개는 메서드다. 학생이 만들어질 때 이름과 학년을 받도록 생성자를 사용했다. 필드는 private으로 보호하고, 필요한 정보만 메서드로 제공했다.

중요한 것은 문법을 하나씩 세는 것이 아니라, 이 클래스가 "학생"이라는 대상을 꽤 그럴듯하게 표현하고 있다는 점이다. 이것이 바로 객체지향의 시작이다.

객체와 참조 변수: 눈에 안 보이지만 꼭 알아야 할 개념

초보자가 자주 헷갈리는 부분이 하나 있다. 다음 코드를 보자.

Car car1 = new Car("Sedan", "Black");
Car car2 = car1;

이때 car2는 car1과 똑같은 내용을 가진 새로운 자동차가 아니다. 두 변수는 같은 객체를 가리킨다. Java에서 객체 변수는 객체 자체를 통째로 담는 것이 아니라, 보통 그 객체를 가리키는 참조를 저장한다고 이해하면 된다.

그래서 아래 코드는 같은 객체의 속도를 바꾸게 된다.

car2.speed = 50;
System.out.println(car1.speed);  // 50

이 현상은 처음엔 이상하게 느껴질 수 있다. 하지만 나중에 객체를 메서드에 전달하거나, 컬렉션에 담거나, 여러 곳에서 공유할 때 아주 중요하게 작용한다.

지금 단계에서는 다음 정도만 분명히 기억하면 충분하다.

  • new를 사용하면 객체가 만들어진다.

  • 변수에는 그 객체를 가리키는 값이 들어간다.

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

null: 아무 객체도 가리키지 않는 상태

객체 참조 변수가 항상 실제 객체를 가리키는 것은 아니다. 아무것도 가리키지 않는 상태를 null이라고 한다.

Car car = null;

이 상태에서 car.speed처럼 필드에 접근하거나 car.accelerate()처럼 메서드를 호출하면 오류가 발생한다. 이것이 흔히 말하는 NullPointerException이다.

Car car = null;
car.accelerate();  // 오류 발생

null은 아직 객체가 없음을 나타내는 특별한 값이다. 초반에는 단순히 "빈 객체"라고 오해하기 쉬운데, 실제로는 객체가 없는 상태다. 그래서 사용 전에 객체가 만들어졌는지 확인하는 습관이 중요하다.

static과 객체의 차이 맛보기

이번 장의 중심은 객체지만, 클래스 안에는 객체에 속하지 않고 클래스 자체에 속하는 요소도 있다. 바로 static이다. 지금은 깊게 들어가기보다 감만 잡자.

예를 들어 학생 수를 세는 기능을 만들고 싶다고 해 보자. 학생 한 명의 이름이나 점수는 각 객체마다 다르다. 하지만 전체 학생 수는 특정 학생 개인의 것이 아니라 Student 클래스 전체에 공통된 정보다. 이럴 때 static을 사용할 수 있다.

public class Student {
    String name;
    static int count = 0;

    Student(String name) {
        this.name = name;
        count++;
    }
}
public class Main {
    public static void main(String[] args) {
        new Student("김자바");
        new Student("박자바");

        System.out.println(Student.count);
    }
}

name은 객체마다 다르지만, count는 클래스 전체가 공유한다. 객체지향 입문 단계에서는 객체마다 따로 있어야 하는가, 모두가 함께 써야 하는가를 구분하는 습관이 중요하다.

객체지향적으로 생각하는 연습법

처음에는 클래스를 설계하는 일이 어렵게 느껴진다. 어디까지를 한 객체의 책임으로 둘지 감이 잘 안 오기 때문이다. 이럴 때는 현실의 명사를 떠올리면 도움이 된다.

예를 들어 쇼핑몰 프로그램을 만든다면 다음과 같은 명사가 보인다.

  • 상품

  • 회원

  • 장바구니

  • 주문

  • 결제

이 명사들은 클래스 후보가 될 수 있다. 그리고 각 대상이 가진 정보와 행동을 적어 본다. 상품은 이름과 가격을 가지고, 할인 적용이라는 동작이 있을 수 있다. 장바구니는 상품 목록을 가지고, 상품 추가와 삭제 기능이 있을 수 있다.

처음부터 완벽하게 나누려 하지 말고, 다음 순서로 생각하면 좋다.

클래스를 설계할 때 자주 쓰는 질문

첫째, 이 클래스는 무엇을 표현하는가?

둘째, 이 객체가 반드시 가지고 있어야 하는 값은 무엇인가?

셋째, 이 객체가 스스로 해야 자연스러운 일은 무엇인가?

넷째, 외부에서 마음대로 바꾸면 위험한 값은 무엇인가?

이 질문에 답하다 보면 필드, 메서드, 생성자, 접근 제어자의 윤곽이 자연스럽게 잡힌다.

초보자가 자주 하는 실수

객체지향을 처음 배울 때는 비슷한 실수를 반복하기 쉽다. 미리 알고 있으면 훨씬 빨리 익숙해질 수 있다.

1. 클래스와 객체를 구분하지 못한다

Car는 클래스이고, new Car()로 만든 결과가 객체다. 클래스는 설계도이고, 객체는 실제 사용 대상이다. 이 둘을 구분하지 못하면 이후의 모든 개념이 흐려진다.

2. 생성자를 메서드처럼 생각한다

생성자는 객체를 만드는 순간에 호출되는 특별한 구성 요소다. 반환형을 쓰지 않고, 클래스 이름과 같아야 한다. void Car()처럼 작성하면 생성자가 아니라 그냥 메서드가 되어 버린다.

3. 모든 필드를 public으로 열어 둔다

처음에는 편해 보여도 점점 통제가 안 된다. 값의 변경 규칙이 무너지기 쉽다. 특별한 이유가 없다면 필드는 private으로 두고, 필요한 동작만 메서드로 제공하는 습관이 좋다.

4. 객체의 일을 바깥 코드가 대신 다 한다

객체는 단순한 가방이 아니다. 관련된 규칙과 행동을 자기 안에 품어야 한다. 데이터만 객체에 넣고 로직은 전부 밖에 두면 객체지향의 장점을 살리기 어렵다.

5. null 상태를 잊는다

객체가 아직 생성되지 않았거나, 어떤 이유로 비어 있는 상태일 수 있다. 참조 변수를 사용할 때는 항상 실제 객체가 있는지 의식하는 습관이 필요하다.

연습 문제처럼 생각해 보기

다음과 같은 대상을 클래스로 만들어 본다고 상상해 보자.

커피 주문

커피 이름, 가격, 온도 정보를 저장하는 필드가 필요할 수 있다. 주문 정보를 출력하는 메서드, 아이스와 핫을 바꾸는 메서드를 만들 수도 있다.

게임 캐릭터

이름, 직업, 체력, 마나가 필요할 수 있다. 공격하기, 회복하기, 상태 출력하기 같은 메서드를 생각할 수 있다.

전등

전원 상태를 나타내는 필드가 필요하다. 켜기, 끄기, 상태 확인 메서드를 만들 수 있다.

이런 식으로 현실의 대상을 클래스와 객체로 바꿔 보는 연습을 자주 하면 객체지향 감각이 빨리 생긴다. 처음에는 정답보다 설계 이유를 설명할 수 있는지가 더 중요하다.

이번 장의 핵심 정리

이번 장에서 꼭 붙잡아야 할 내용은 다음과 같다.

  • 클래스는 객체를 만들기 위한 설계도다.

  • 객체는 클래스 기반으로 실제 생성된 대상이다.

  • 필드는 객체의 상태를 나타낸다.

  • 메서드는 객체의 행동을 나타낸다.

  • 생성자는 객체가 만들어질 때 필요한 초기화를 담당한다.

  • 접근 제어자는 객체의 데이터를 안전하게 보호한다.

  • 좋은 객체는 자기 데이터를 스스로 관리한다.

이제부터 Java 코드를 볼 때는 단순히 "명령을 순서대로 적은 프로그램"이 아니라, 서로 역할을 나누어 협력하는 객체들의 세계로 바라보면 좋다. 그렇게 보는 순간 Java는 훨씬 더 입체적으로 느껴진다.

마무리

객체지향은 단번에 완전히 이해되는 개념이 아니다. 하지만 이번 장에서 배운 클래스, 객체, 필드, 메서드, 생성자, 접근 제어자를 바탕으로 계속 예제를 만들어 보면 어느 순간 감이 잡힌다.

중요한 것은 어려운 이론 용어를 외우는 것이 아니다. "이 데이터를 누가 가져야 할까?", "이 동작은 누가 하는 게 자연스러울까?", "어떤 값은 왜 감춰야 할까?" 같은 질문을 습관처럼 던지는 것이다.

그 질문을 던지기 시작했다면, 이미 Java를 Java답게 쓰는 길에 들어선 것이다.

다음 장에서는 여기서 한 걸음 더 나아가 캡슐화, 상속, 다형성, 추상화를 통해 객체지향의 핵심을 더 깊이 살펴보겠다. 이제 클래스와 객체라는 기본 무기를 손에 넣었으니, 진짜 객체지향의 맛을 볼 준비가 되었다.

책 목록

처음부터 실무까지 단계별로 배우는 JAVA 학습

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기