7장. 객체지향 프로그래밍(OOP) 기초
객체지향 프로그래밍이란?
OOP (Object-Oriented Programming)
객체지향 프로그래밍은 프로그램을 객체(Object) 단위로 설계하고 구현하는 프로그래밍 패러다임입니다. Java는 객체지향 언어로, 모든 코드는 클래스 안에 작성됩니다.
객체지향 프로그래밍의 핵심 개념
- 캡슐화 (Encapsulation): 데이터와 메서드를 하나로 묶어 관리
- 상속 (Inheritance): 기존 클래스를 확장하여 새로운 클래스 생성
- 다형성 (Polymorphism): 하나의 인터페이스로 여러 형태 구현
- 추상화 (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)는 객체가 생성될 때 자동으로 호출되는 특별한 메서드입니다. 생성자는 객체의 초기화를 담당합니다.
생성자의 특징
- 메서드명이 클래스명과 동일
- 반환 타입이 없음 (void도 사용하지 않음)
- 객체 생성 시 자동 호출
- 오버로딩 가능
기본 생성자 (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의 사용 목적
- 필드와 매개변수 구분: 필드와 매개변수 이름이 같을 때 구분
- 다른 생성자 호출: 생성자에서 다른 생성자 호출
- 현재 객체 반환: 메서드에서 현재 객체 반환
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();
}
}
연습 문제
기본 클래스 만들기
Book클래스를 만들고, 제목, 저자, 가격 필드를 가진 객체를 생성하세요.
생성자 사용
Person클래스를 만들고, 이름과 나이를 받는 생성자를 작성하세요.
Getter/Setter
Student클래스의 필드를 private로 선언하고, getter/setter 메서드를 작성하세요.
this 키워드
- 생성자와 메서드에서 this 키워드를 사용하는 예제를 작성하세요.
캡슐화
BankAccount클래스를 만들고, 잔액을 private로 선언한 후 입금/출금 메서드를 작성하세요.
종합 예제
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 |