본문 바로가기
  • 코딩, 허쌤이 떠먹여 줄게
BackEnd/Java

7장. 객체지향 프로그래밍(OOP) 기초

by 허쌤 2026. 1. 1.

7장. 객체지향 프로그래밍(OOP) 기초

객체지향 프로그래밍이란?

OOP (Object-Oriented Programming)

객체지향 프로그래밍은 프로그램을 객체(Object) 단위로 설계하고 구현하는 프로그래밍 패러다임입니다. Java는 객체지향 언어로, 모든 코드는 클래스 안에 작성됩니다.

객체지향 프로그래밍의 핵심 개념

  1. 캡슐화 (Encapsulation): 데이터와 메서드를 하나로 묶어 관리
  2. 상속 (Inheritance): 기존 클래스를 확장하여 새로운 클래스 생성
  3. 다형성 (Polymorphism): 하나의 인터페이스로 여러 형태 구현
  4. 추상화 (Abstraction): 복잡한 것을 단순하게 표현

객체지향 프로그래밍의 장점

  • 코드 재사용: 클래스를 재사용하여 개발 시간 단축
  • 유지보수 용이: 클래스 단위로 수정이 가능
  • 모듈화: 프로그램을 작은 단위로 나누어 관리
  • 확장성: 새로운 기능을 쉽게 추가 가능

클래스와 객체

클래스 (Class)

클래스는 객체를 만들기 위한 설계도 또는 템플릿입니다. 클래스는 객체가 가질 속성(변수)과 행동(메서드)을 정의합니다.

클래스의 구성 요소

public class 클래스명 {
    // 필드 (Field) - 객체의 속성
    변수타입 변수명;

    // 메서드 (Method) - 객체의 행동
    반환타입 메서드명() {
        // 메서드 본문
    }
}

클래스 예제

public class Student {
    // 필드 (속성)
    String name;
    int age;
    String major;

    // 메서드 (행동)
    public void study() {
        System.out.println(name + "이(가) 공부합니다.");
    }

    public void introduce() {
        System.out.println("이름: " + name + ", 나이: " + age + ", 전공: " + major);
    }
}

객체 (Object)

객체는 클래스를 기반으로 생성된 실제 인스턴스(Instance)입니다. 하나의 클래스로 여러 개의 객체를 만들 수 있습니다.

객체와 인스턴스

  • 클래스: 설계도
  • 객체/인스턴스: 설계도를 바탕으로 만든 실제 제품
// 클래스: Student (설계도)
// 객체: student1, student2 (실제 제품)
Student student1 = new Student();
Student student2 = new Student();

클래스 vs 객체

구분 클래스 객체
정의 객체를 만들기 위한 설계도 클래스로부터 생성된 실제 인스턴스
메모리 클래스 정의만 메모리에 로드 객체 생성 시 메모리 할당
개수 하나의 클래스 여러 개의 객체 생성 가능
예시 Student 클래스 student1, student2 객체

객체 생성과 사용

객체 생성

객체는 new 키워드를 사용하여 생성합니다.

기본 형식

클래스명 객체명 = new 클래스명();

객체 생성 예제

// Student 클래스의 객체 생성
Student student1 = new Student();
Student student2 = new Student();

객체 사용

객체의 필드와 메서드에 접근하려면 점(.) 연산자를 사용합니다.

필드 접근

// 필드에 값 할당
student1.name = "홍길동";
student1.age = 20;
student1.major = "컴퓨터공학";

// 필드 값 읽기
System.out.println(student1.name);

메서드 호출

// 메서드 호출
student1.study();
student1.introduce();

완전한 예제

public class Student {
    // 필드
    String name;
    int age;
    String major;

    // 메서드
    public void study() {
        System.out.println(name + "이(가) 공부합니다.");
    }

    public void introduce() {
        System.out.println("이름: " + name + ", 나이: " + age + ", 전공: " + major);
    }

    public static void main(String[] args) {
        // 객체 생성
        Student student1 = new Student();
        Student student2 = new Student();

        // 객체1 사용
        student1.name = "홍길동";
        student1.age = 20;
        student1.major = "컴퓨터공학";

        // 객체2 사용
        student2.name = "김철수";
        student2.age = 21;
        student2.major = "전자공학";

        // 메서드 호출
        student1.introduce();
        student1.study();

        student2.introduce();
        student2.study();
    }
}

객체 참조

객체 변수는 실제 객체를 저장하는 것이 아니라, 객체의 주소(참조)를 저장합니다.

Student student1 = new Student();
Student student2 = student1;  // student2도 같은 객체를 참조

student1.name = "홍길동";
System.out.println(student2.name);  // "홍길동" (같은 객체를 참조하므로)

생성자 (Constructor)

생성자란?

생성자(Constructor)는 객체가 생성될 때 자동으로 호출되는 특별한 메서드입니다. 생성자는 객체의 초기화를 담당합니다.

생성자의 특징

  1. 메서드명이 클래스명과 동일
  2. 반환 타입이 없음 (void도 사용하지 않음)
  3. 객체 생성 시 자동 호출
  4. 오버로딩 가능

기본 생성자 (Default Constructor)

생성자를 정의하지 않으면 Java가 자동으로 기본 생성자를 제공합니다.

public class Student {
    String name;
    int age;

    // 생성자가 없으면 자동으로 기본 생성자 제공
    // public Student() { }
}

생성자 정의

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

    // 생성자 정의
    public Student(String name, int age, String major) {
        this.name = name;
        this.age = age;
        this.major = major;
    }
}

생성자 사용

// 생성자를 사용한 객체 생성
Student student1 = new Student("홍길동", 20, "컴퓨터공학");
Student student2 = new Student("김철수", 21, "전자공학");

생성자 오버로딩

여러 개의 생성자를 정의할 수 있습니다.

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

    // 생성자 1: 모든 필드 초기화
    public Student(String name, int age, String major) {
        this.name = name;
        this.age = age;
        this.major = major;
    }

    // 생성자 2: 이름과 나이만 초기화
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        this.major = "미정";
    }

    // 생성자 3: 이름만 초기화
    public Student(String name) {
        this.name = name;
        this.age = 0;
        this.major = "미정";
    }

    // 생성자 4: 기본 생성자
    public Student() {
        this.name = "이름 없음";
        this.age = 0;
        this.major = "미정";
    }
}

생성자 체이닝

한 생성자에서 다른 생성자를 호출할 수 있습니다.

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

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

    public Student(String name, int age) {
        this(name, age, "미정");  // 다른 생성자 호출
    }

    public Student(String name) {
        this(name, 0, "미정");  // 다른 생성자 호출
    }
}

this 키워드

this란?

this는 현재 객체를 가리키는 참조 변수입니다. 생성자나 메서드 내에서 현재 객체의 필드나 메서드에 접근할 때 사용합니다.

this의 사용 목적

  1. 필드와 매개변수 구분: 필드와 매개변수 이름이 같을 때 구분
  2. 다른 생성자 호출: 생성자에서 다른 생성자 호출
  3. 현재 객체 반환: 메서드에서 현재 객체 반환

this로 필드 접근

public class Student {
    String name;
    int age;

    public Student(String name, int age) {
        // this.name은 필드, name은 매개변수
        this.name = name;
        this.age = age;
    }
}

this로 메서드 호출

public class Student {
    String name;
    int age;

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

    public void printInfo() {
        System.out.println("이름: " + this.name + ", 나이: " + this.age);
        // this는 생략 가능하지만 명시적으로 사용하는 것이 좋음
    }
}

this로 생성자 호출

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

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

    public Student(String name, int age) {
        this(name, age, "미정");  // 다른 생성자 호출
    }

    public Student(String name) {
        this(name, 0);  // 다른 생성자 호출
    }
}

this 주의사항

  • static 메서드에서는 사용 불가: static 메서드는 객체에 속하지 않으므로 this가 없음
  • 생성자에서 this() 호출은 첫 번째 줄에만 가능
public class Student {
    String name;

    public Student(String name) {
        // this() 호출은 반드시 첫 번째 줄에
        this(name, 0);  // OK
        // 다른 코드는 여기서부터 작성
    }

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

접근제어자 (Access Modifier)

접근제어자란?

접근제어자는 클래스, 필드, 메서드의 접근 범위를 제어하는 키워드입니다.

접근제어자의 종류

접근제어자 접근 범위 설명
public 모든 패키지 어디서든 접근 가능
protected 같은 패키지 + 상속 관계 같은 패키지와 자식 클래스에서 접근 가능
default (package-private) 같은 패키지 접근제어자를 명시하지 않으면 default, 같은 패키지에서만 접근 가능
private 같은 클래스 같은 클래스 내에서만 접근 가능

접근제어자 사용 예제

public class Student {
    // public: 어디서든 접근 가능
    public String name;

    // private: 같은 클래스 내에서만 접근 가능
    private int age;
    private String major;

    // public 메서드
    public void introduce() {
        System.out.println("이름: " + name);
        System.out.println("나이: " + age);  // 같은 클래스이므로 접근 가능
    }

    // private 메서드
    private void calculateGrade() {
        // 내부에서만 사용하는 메서드
    }
}

캡슐화와 접근제어자

캡슐화를 위해 필드는 private로 선언하고, 접근을 위한 메서드(getter/setter)를 제공합니다.

Getter와 Setter

public class Student {
    // private 필드
    private String name;
    private int age;
    private String major;

    // Getter: 필드 값을 읽는 메서드
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getMajor() {
        return major;
    }

    // Setter: 필드 값을 설정하는 메서드
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        if (age >= 0 && age <= 150) {  // 유효성 검사
            this.age = age;
        } else {
            System.out.println("유효하지 않은 나이입니다.");
        }
    }

    public void setMajor(String major) {
        this.major = major;
    }
}

접근제어자 사용 예제

public class BankAccount {
    // private: 외부에서 직접 접근 불가
    private String accountNumber;
    private double balance;

    // 생성자
    public BankAccount(String accountNumber, double balance) {
        this.accountNumber = accountNumber;
        this.balance = balance;
    }

    // public: 외부에서 접근 가능
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println(amount + "원 입금되었습니다.");
        }
    }

    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println(amount + "원 출금되었습니다.");
        } else {
            System.out.println("잔액이 부족합니다.");
        }
    }

    // Getter
    public double getBalance() {
        return balance;
    }

    public String getAccountNumber() {
        return accountNumber;
    }
}

객체지향 프로그래밍 종합 예제

예제: Car 클래스

public class Car {
    // 필드 (private로 캡슐화)
    private String brand;
    private String model;
    private int year;
    private double speed;

    // 생성자
    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        this.speed = 0.0;
    }

    // Getter 메서드
    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    public double getSpeed() {
        return speed;
    }

    // 메서드
    public void accelerate(double amount) {
        if (amount > 0) {
            speed += amount;
            System.out.println("속도가 " + amount + "km/h 증가했습니다.");
        }
    }

    public void brake(double amount) {
        if (amount > 0 && speed >= amount) {
            speed -= amount;
            System.out.println("속도가 " + amount + "km/h 감소했습니다.");
        } else if (speed < amount) {
            speed = 0;
            System.out.println("차량이 정지했습니다.");
        }
    }

    public void displayInfo() {
        System.out.println("브랜드: " + brand);
        System.out.println("모델: " + model);
        System.out.println("연식: " + year);
        System.out.println("현재 속도: " + speed + "km/h");
    }

    public static void main(String[] args) {
        // 객체 생성
        Car car1 = new Car("현대", "소나타", 2023);
        Car car2 = new Car("기아", "K5", 2022);

        // 메서드 호출
        car1.displayInfo();
        car1.accelerate(50);
        car1.accelerate(30);
        car1.brake(20);
        car1.displayInfo();

        System.out.println();

        car2.displayInfo();
        car2.accelerate(60);
        car2.displayInfo();
    }
}

연습 문제

  1. 기본 클래스 만들기

    • Book 클래스를 만들고, 제목, 저자, 가격 필드를 가진 객체를 생성하세요.
  2. 생성자 사용

    • Person 클래스를 만들고, 이름과 나이를 받는 생성자를 작성하세요.
  3. Getter/Setter

    • Student 클래스의 필드를 private로 선언하고, getter/setter 메서드를 작성하세요.
  4. this 키워드

    • 생성자와 메서드에서 this 키워드를 사용하는 예제를 작성하세요.
  5. 캡슐화

    • BankAccount 클래스를 만들고, 잔액을 private로 선언한 후 입금/출금 메서드를 작성하세요.
  6. 종합 예제

    • Rectangle 클래스를 만들고, 너비와 높이를 설정하여 넓이와 둘레를 계산하는 메서드를 작성하세요.

다음 장 예고

다음 장에서는 상속(Inheritance)을 통해 기존 클래스를 확장하고 코드를 재사용하는 방법을 학습합니다.

'BackEnd > Java' 카테고리의 다른 글

9장. 컬렉션 프레임워크  (0) 2026.01.02
# 8장. 객체지향 핵심 개념  (0) 2026.01.01
6장. 메서드(Method)  (0) 2025.12.31
5장. 배열과 문자열  (0) 2025.12.30
4장. 제어문  (0) 2025.12.30