Java 26일 코스 - Day 9: 클래스와 객체

Day 9: 클래스와 객체

객체지향 프로그래밍(OOP)에서 클래스는 설계도이고, 객체는 그 설계도로 만든 실제 사물입니다. 자동차 설계도(클래스)로 여러 대의 자동차(객체)를 만들 수 있는 것과 같습니다. Java는 순수 객체지향 언어로, 모든 코드가 클래스 안에 존재합니다.

클래스 정의와 객체 생성

필드(속성)와 메서드(행동)로 클래스를 설계합니다.

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

    // 메서드 (행동)
    void introduce() {
        System.out.println("안녕하세요, " + name + "입니다.");
        System.out.println("전공: " + major + ", GPA: " + gpa);
    }

    void study(String subject) {
        System.out.println(name + "이(가) " + subject + "을(를) 공부합니다.");
    }

    boolean isPassing() {
        return gpa >= 2.0;
    }

    public static void main(String[] args) {
        // 객체 생성
        Student student1 = new Student();
        student1.name = "홍길동";
        student1.age = 22;
        student1.major = "컴퓨터공학";
        student1.gpa = 3.8;

        Student student2 = new Student();
        student2.name = "김영희";
        student2.age = 21;
        student2.major = "경영학";
        student2.gpa = 4.2;

        student1.introduce();
        student2.introduce();
        student1.study("Java");
        System.out.println("합격 여부: " + student1.isPassing());
    }
}

생성자 (Constructor)

객체를 생성할 때 자동으로 호출되는 특수한 메서드입니다. 클래스 이름과 같고, 반환 타입이 없습니다.

public class BankAccount {
    String owner;
    String accountNumber;
    long balance;

    // 기본 생성자
    BankAccount() {
        this.owner = "미지정";
        this.accountNumber = "000-000-000";
        this.balance = 0;
    }

    // 매개변수 있는 생성자
    BankAccount(String owner, String accountNumber) {
        this.owner = owner;
        this.accountNumber = accountNumber;
        this.balance = 0;
    }

    // 모든 필드를 초기화하는 생성자
    BankAccount(String owner, String accountNumber, long balance) {
        this.owner = owner;
        this.accountNumber = accountNumber;
        this.balance = balance;
    }

    void deposit(long amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println(amount + "원 입금. 잔액: " + balance + "원");
        }
    }

    void withdraw(long amount) {
        if (amount > 0 && balance >= amount) {
            balance -= amount;
            System.out.println(amount + "원 출금. 잔액: " + balance + "원");
        } else {
            System.out.println("잔액 부족! 현재 잔액: " + balance + "원");
        }
    }

    void showInfo() {
        System.out.println("[" + accountNumber + "] " + owner + " - 잔액: " + balance + "원");
    }

    public static void main(String[] args) {
        BankAccount acc1 = new BankAccount();
        BankAccount acc2 = new BankAccount("홍길동", "110-234-5678");
        BankAccount acc3 = new BankAccount("김영희", "110-987-6543", 1000000);

        acc2.deposit(500000);
        acc2.withdraw(200000);
        acc2.showInfo();

        acc3.showInfo();
    }
}

this 키워드와 메서드 체이닝

this는 현재 객체 자신을 가리킵니다. 필드와 매개변수 이름이 같을 때 구분하거나, 메서드 체이닝 패턴에 사용합니다.

public class Pizza {
    String size;
    String dough;
    boolean cheese;
    boolean pepperoni;
    boolean mushroom;

    Pizza(String size) {
        this.size = size;
        this.dough = "기본";
        this.cheese = false;
        this.pepperoni = false;
        this.mushroom = false;
    }

    // 메서드 체이닝: this를 반환하여 연속 호출 가능
    Pizza setDough(String dough) {
        this.dough = dough;
        return this;
    }

    Pizza addCheese() {
        this.cheese = true;
        return this;
    }

    Pizza addPepperoni() {
        this.pepperoni = true;
        return this;
    }

    Pizza addMushroom() {
        this.mushroom = true;
        return this;
    }

    void describe() {
        System.out.println("=== 피자 주문 ===");
        System.out.println("크기: " + size);
        System.out.println("도우: " + dough);
        System.out.println("치즈: " + (cheese ? "추가" : "없음"));
        System.out.println("페퍼로니: " + (pepperoni ? "추가" : "없음"));
        System.out.println("버섯: " + (mushroom ? "추가" : "없음"));
    }

    public static void main(String[] args) {
        // 메서드 체이닝으로 깔끔하게 설정
        Pizza myPizza = new Pizza("라지")
            .setDough("씬")
            .addCheese()
            .addPepperoni()
            .addMushroom();

        myPizza.describe();
    }
}

정적 멤버 (static)

클래스 레벨에서 공유되는 필드와 메서드입니다. 객체를 만들지 않아도 사용할 수 있습니다.

public class Counter {
    // static 필드: 모든 객체가 공유
    static int totalCount = 0;

    // 인스턴스 필드: 각 객체마다 별도
    String name;
    int id;

    Counter(String name) {
        this.name = name;
        totalCount++;
        this.id = totalCount;
    }

    // static 메서드: 클래스 이름으로 호출
    static int getTotalCount() {
        return totalCount;
    }

    // 인스턴스 메서드
    void showInfo() {
        System.out.println("ID: " + id + ", 이름: " + name);
    }

    public static void main(String[] args) {
        System.out.println("총 개수: " + Counter.getTotalCount()); // 0

        Counter c1 = new Counter("첫 번째");
        Counter c2 = new Counter("두 번째");
        Counter c3 = new Counter("세 번째");

        c1.showInfo(); // ID: 1
        c2.showInfo(); // ID: 2
        c3.showInfo(); // ID: 3

        System.out.println("총 개수: " + Counter.getTotalCount()); // 3
    }
}

오늘의 연습문제

  1. 도서 관리: Book 클래스를 만드세요. 필드: 제목, 저자, 가격, ISBN. 생성자 오버로딩(2개 이상), showInfo() 메서드, applyDiscount(int percent) 메서드를 구현하세요.

  2. 좌표 계산기: Point 클래스를 만드세요. 필드: x, y (double). 두 점 사이의 거리를 구하는 distanceTo(Point other) 메서드와, 중점을 반환하는 midPoint(Point other) 메서드를 구현하세요.

  3. 사원 번호 자동 생성: Employee 클래스에서 static 변수를 사용하여 객체가 생성될 때마다 “EMP-001”, “EMP-002” 형식의 사원번호가 자동 부여되도록 구현하세요.

이 글이 도움이 되었나요?