객체지향 프로그래밍 기초와 클래스 설계
📚 오늘 배운 내용 요약
| 주제 | 핵심 내용 |
|---|
| 클래스(Class) | 객체를 만들기 위한 설계도 |
| 객체(Object) | 클래스를 기반으로 생성된 실체 |
| 인스턴스(Instance) | 메모리에 생성된 객체 |
| 필드(Field) | 객체가 가지는 속성(데이터) |
| 메서드(Method) | 객체가 수행하는 기능 |
| 생성자(Constructor) | 객체 생성 시 호출되는 특별한 메서드 |
| this | 현재 인스턴스 자신을 가리키는 키워드 |
| static | 객체 생성 없이 클래스 차원에서 공유되는 멤버 |
| 오버로딩(Overloading) | 같은 이름의 메서드를 여러 개 정의 |
| 접근제어자 | 외부 접근 범위를 제어 |
| 캡슐화 | 데이터를 보호하고 검증하는 객체지향 원칙 |
1) 객체 생성과 메모리 구조
| 학습 내용 | 설명 |
|---|
| 객체 생성 | new 키워드로 객체 생성 |
| 참조 변수 | 객체의 주소를 저장 |
| null | 객체와 연결되지 않은 상태 |
| 기본값 초기화 | 객체 생성 시 기본값 자동 할당 |
| this | 현재 객체 자신의 필드 접근 |
| static 변수 | 모든 객체가 공유 |
public class Example01 {
public static int totalCount = 0;
public static void main(String[] args) {
Instructor instructor = new Instructor();
System.out.println(instructor.name);
Instructor copiedInstructor = instructor;
copiedInstructor.name = "김강사";
instructor.speak("학생", 10);
System.out.println(instructor.name);
}
}
class Instructor {
String name;
int age;
static int count;
void speak(String target, int number) {
System.out.println(target);
System.out.println(this.name);
Example01.totalCount++;
}
}
- new를 통해 힙 메모리에 객체 생성
- 참조 변수는 객체 주소 저장
- 동일한 객체를 여러 참조 변수가 가리킬 수 있음
- this를 통해 현재 객체의 필드 접근
- static 변수는 객체가 아닌 클래스에 소속
| 느낀 점 | 내용 |
|---|
| 참조 개념 중요 | 변수 자체가 객체가 아니라 객체 주소를 저장 |
| static 이해 필요 | 객체마다 생성되는 것이 아니라 공유됨 |
| this 역할 이해 | 지역변수와 필드 구분 가능 |
2) 클래스와 인스턴스
| 학습 내용 | 설명 |
|---|
| 클래스 | 객체 설계도 |
| 인스턴스 | 실제 생성된 객체 |
| 멤버 변수 | 객체마다 별도 보유 |
| 참조 비교 | == 연산자 사용 |
public class Example02 {
public static void main(String[] args) {
Vehicle vehicleA = new Vehicle();
vehicleA.model = "소나타";
Vehicle vehicleB = new Vehicle();
vehicleB.model = "아반떼";
vehicleA.increaseSpeed();
vehicleA.increaseSpeed();
vehicleB.increaseSpeed();
}
}
class Vehicle {
String model;
int speed;
void increaseSpeed() {
speed += 10;
}
}
- 객체마다 별도의 필드 공간 보유
- 같은 클래스라도 다른 인스턴스는 독립적
- == 는 객체 주소 비교
| 느낀 점 | 내용 |
|---|
| 객체는 독립적 | 같은 클래스여도 상태는 서로 다름 |
| 참조 비교 이해 | ==는 값이 아니라 주소 비교 |
| 인스턴스 개념 정립 | 클래스와 객체를 구분해야 함 |
3) 메서드와 오버로딩
| 학습 내용 | 설명 |
|---|
| 메서드 | 객체의 기능 정의 |
| 반환값 | return을 통해 결과 전달 |
| 매개변수 | 외부 데이터 전달 |
| 오버로딩 | 같은 이름의 메서드 여러 개 정의 |
| 가변인자 | 개수가 정해지지 않은 매개변수 |
class Calculator {
int sum(int a, int b) {
return a + b;
}
String sum(String a, String b) {
return a + b;
}
int sum(int... numbers) {
int result = 0;
for (int value : numbers) {
result += value;
}
return result;
}
}
- 메서드 이름은 동일
- 매개변수 타입이나 개수가 다르면 오버로딩 가능
- 가변인자로 여러 개의 값 처리 가능
| 느낀 점 | 내용 |
|---|
| 코드 가독성 향상 | 같은 기능을 같은 이름으로 표현 |
| 컴파일러 구분 기준 이해 | 매개변수 타입과 개수 |
| 오버로딩 활용 가능 | 다양한 입력 처리 가능 |
4) 생성자(Constructor)
| 학습 내용 | 설명 |
|---|
| 생성자 | 객체 생성 시 호출 |
| 기본 생성자 | 매개변수가 없는 생성자 |
| 생성자 오버로딩 | 여러 생성자 정의 가능 |
| this() | 다른 생성자 호출 |
class User {
String name;
int age;
String address;
User() {
}
User(String name, int age) {
this.name = name;
this.age = age;
}
User(String name, int age, String address) {
this(name, age);
this.address = address;
}
}
- 생성 시 초기값 설정
- 생성자끼리 재사용 가능
- this()를 이용해 코드 중복 제거
| 느낀 점 | 내용 |
|---|
| 객체 초기화 중요 | 생성 시점에 데이터 설정 가능 |
| 코드 재사용 가능 | 생성자 연결 활용 |
| this 활용 숙지 | 필드와 매개변수 구분 |
5) static
| 학습 내용 | 설명 |
|---|
| static 변수 | 클래스가 공유 |
| static 메서드 | 객체 생성 없이 호출 |
| final static | 상수 선언 |
| 클래스 영역 | 프로그램 시작 시 생성 |
class CounterUtil {
static int count = 0;
static void increase() {
count++;
}
static void increase(int amount) {
count += amount;
}
}
- 객체 없이 사용 가능
- 모든 객체가 같은 값 공유
- 유틸리티 기능 구현에 적합
| 느낀 점 | 내용 |
|---|
| 객체와 클래스 구분 | static은 클래스 소속 |
| 메모리 절약 | 객체마다 생성되지 않음 |
| 활용도 높음 | 유틸 클래스에 자주 사용 |
6) Nested Class와 static 내부 클래스
| 학습 내용 | 설명 |
|---|
| Nested Class | 클래스 내부 클래스 |
| static 내부 클래스 | 외부 객체 없이 사용 |
| record | 데이터 저장 전용 객체 |
public class Example06 {
public static class Helper {
static int count;
public static void increase() {
count++;
}
}
}
- 특정 클래스 내부에 정의
- 관련 기능을 묶어서 관리 가능
| 느낀 점 | 내용 |
|---|
| 코드 구조화 가능 | 관련 클래스 묶기 |
| 유지보수 향상 | 응집도 증가 |
| record 활용 가능 | DTO 대체 가능 |
7) 접근 제어자
| 접근제어자 | 같은 클래스 | 같은 패키지 | 다른 패키지 | 상속 |
|---|
| private | O | X | X | X |
| default | O | O | X | X |
| protected | O | O | X | O |
| public | O | O | O | O |
public class User {
private String password;
public String name;
}
- private은 외부 접근 차단
- public은 모든 곳에서 접근 가능
| 느낀 점 | 내용 |
|---|
| 정보 은닉 중요 | 내부 구현 보호 |
| 캡슐화 기반 | 객체 안정성 증가 |
| 접근 범위 설계 필요 | 무조건 public 사용 지양 |
8) 캡슐화(Encapsulation)
| 학습 내용 | 설명 |
|---|
| 캡슐화 | 데이터 보호 |
| Getter | 데이터 조회 |
| Setter | 데이터 수정 |
| 검증 로직 | 잘못된 데이터 차단 |
| 방어적 복사 | 원본 데이터 보호 |
class ProductManager {
private String productName;
private int productPrice;
public void setProductName(String productName) {
if(productName.length() != 3){
return;
}
this.productName = productName;
}
public void setProductPrice(int productPrice) {
if(productPrice < 1 || productPrice > 1000){
return;
}
this.productPrice = productPrice;
}
}
- 직접 수정 불가
- Setter를 통한 검증 수행
- 객체 상태 보호 가능
| 느낀 점 | 내용 |
|---|
| 데이터 무결성 확보 | 잘못된 값 차단 |
| 유지보수성 향상 | 검증 로직 집중 |
| 객체지향 핵심 원칙 체감 | 캡슐화의 필요성 이해 |
🚨 직면한 문제와 해결 과정
문제 1. static은 언제 사용하는가?
고민한 내용
| 의문점 | 내용 |
|---|
| 객체 없이 사용하는 이유는? | 굳이 new를 해야 하나? |
| 인스턴스 변수와 차이는? | 메모리 구조가 다른가? |
시도한 방법
class User {
static int totalUserCount;
int age;
}
해결
| 구분 | static 변수 | 인스턴스 변수 |
|---|
| 소속 | 클래스 | 객체 |
| 생성 시점 | 프로그램 실행 | 객체 생성 |
| 공유 여부 | 공유 | 개별 보유 |
| 사용 방식 | 클래스명.변수 | 객체명.변수 |
배운 점
- 공통 데이터는 static 사용
- 객체 상태 데이터는 인스턴스 변수 사용
문제 2. 오버로딩은 왜 필요한가?
고민한 내용
calculator.sum(1, 2);
calculator.sum("1", "2");
calculator.sum(1, 2, 3);
해결
| 장점 | 설명 |
|---|
| 가독성 | 같은 기능은 같은 이름 |
| 편의성 | 다양한 입력 처리 |
| 유지보수 | 메서드 이름 증가 방지 |
배운 점
- 이름보다 행위가 중요
- 매개변수로 기능 구분 가능
문제 3. 객체(Object)와 인스턴스(Instance)의 차이
고민한 내용
| 용어 | 헷갈린 이유 |
|---|
| 객체 | 실제 데이터인가? |
| 인스턴스 | 객체와 같은 말인가? |
해결
| 개념 | 설명 |
|---|
| 클래스 | 설계도 |
| 객체 | 설계도로 만든 실체 |
| 인스턴스 | 메모리에 생성된 객체 |
예시
Car myCar = new Car();
- Car → 클래스
- new Car() → 객체
- myCar → 객체를 참조하는 변수
- 생성된 Car → 인스턴스
배운 점
객체와 인스턴스는 거의 같은 의미로 사용되지만,
- 클래스 입장에서 보면 "인스턴스"
- 실제 존재하는 데이터 입장에서 보면 "객체"
라고 이해하면 된다.
최종 정리
| 핵심 개념 | 오늘 이해한 내용 |
|---|
| 클래스 | 객체 설계도 |
| 객체 | 실제 생성된 데이터 |
| 인스턴스 | 메모리에 존재하는 객체 |
| 생성자 | 객체 초기화 |
| this | 현재 객체 참조 |
| static | 클래스 공유 자원 |
| 오버로딩 | 같은 이름의 메서드 여러 개 |
| 접근제어자 | 접근 범위 제어 |
| 캡슐화 | 데이터 보호 |
| Getter/Setter | 안전한 데이터 접근 |