본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.
CH 3. 객체와 클래스 이해하기
자바 객체 지향 프로그래밍의 핵심: 클래스, 객체, 상속, 그리고 메소드 오버라이딩 🚀
1. 객체 지향 프로그래밍(OOP)이란?
객체 지향 프로그래밍(OOP)은 소프트웨어 시스템에서 데이터를 다루는 데 초점을 맞춘 프로그래밍 패러다임입니다. OOP의 핵심은 객체(Objects)라는 개념에 기반하며, 이 객체는 데이터(fields, attributes, properties)와 해당 데이터를 조작하는 코드(procedures, methods)를 함께 포함할 수 있습니다.
OOP는 현실 세계의 사물과 개념을 소프트웨어로 모델링하는 데 매우 효과적입니다. 예를 들어, '고객'이라는 객체는 '이름', '전화번호', '이메일'과 같은 데이터를 가질 수 있고, '주문하기', '정보 수정하기'와 같은 행동(메소드)을 수행할 수 있습니다.
2. 클래스와 객체의 구성: 설계도와 실체
자바에서 클래스(Class)는 객체를 만들기 위한 설계도 또는 템플릿과 같습니다. 클래스는 객체가 가져야 할 데이터(멤버 변수)와 행동(메소드)을 정의합니다. 객체(Object)는 이 클래스를 바탕으로 생성된 실제 '인스턴스'입니다.
2.1. 클래스의 기본 구성 요소
클래스는 일반적으로 다음 요소들로 구성됩니다.
- 멤버 변수(Member Variables / Fields): 객체의 상태(데이터)를 나타냅니다. 클래스 내부에 선언되며, 객체가 가질 수 있는 속성들을 정의합니다. 예를 들어,
- Customer 클래스에는 name, number, email과 같은 멤버 변수가 있을 수 있습니다.
- 생성자(Constructor): 객체를 생성할 때 호출되는 특별한 종류의 메소드입니다. 생성자는 새 객체를 사용할 준비를 하며, 종종 필수 멤버 변수를 설정하는 데 사용되는 인수를 받습니다.
- 메소드(Methods): 객체의 행동을 나타냅니다. 특정 작업을 수행하는 코드 블록으로, 객체의 데이터를 조작하거나 다른 작업을 수행합니다. 예를 들어,
- Customer 클래스에는 getName(), getNumber(), getEmail()과 같은 메소드가 있을 수 있습니다.
Customer 클래스 예시:
public class Customer {
// 멤버 변수 (Fields) - 고객의 속성
private String name; // 고객 이름
private String number; // 전화번호
private String email; // 이메일
// 생성자 (Constructor) - Customer 객체를 생성할 때 호출
public Customer(String name, String number, String email) { // [cite: 479]
this.name = name; // this 키워드는 현재 객체를 지칭 [cite: 559]
this.number = number;
this.email = email;
}
// 멤버 메소드 (Methods) - 고객 객체의 행동
public String getName() { // [cite: 482]
return name;
}
public String getNumber() {
return number;
}
public String getEmail() {
return email;
}
// 편의 메소드: 고객 정보 출력 (나중에 toString() 오버라이딩으로 대체 가능)
public void printCustomerInfo() {
System.out.println("고객 이름: " + this.name + ", 전화번호: " + this.number + ", 이메일: " + this.email);
}
}
2.2. 객체 생성 및 활용
클래스를 정의했다면, 이제 이 클래스를 이용해 실제 객체를 만들고 사용할 수 있습니다.
public class CustomerApp {
public static void main(String[] args) {
// Customer 클래스를 이용하여 customer1 객체 생성
Customer customer1 = new Customer("김철수", "010-1234-5678", "kim@example.com"); // [cite: 616]
// customer1 객체의 메소드 호출하여 정보 가져오기 및 출력
System.out.println("고객 1 이름: " + customer1.getName());
customer1.printCustomerInfo();
// 전화번호 대신 이메일로 소통하고 싶은 고객 (메소드 오버로딩 또는 다른 생성자 사용 가능)
// 새로운 Customer 객체 생성 시 이메일만 제공하는 생성자도 만들 수 있습니다.
Customer customer2 = new Customer("이영희", null, "lee@example.com"); // 전화번호는 null [cite: 567]
customer2.printCustomerInfo();
}
}
2.3. 캡슐화와 접근 제어
캡슐화(Encapsulation)는 OOP의 중요한 원칙 중 하나로, 데이터(멤버 변수)와 이 데이터를 다루는 메소드를 하나로 묶는 것을 의미합니다. 또한, 외부 코드에서 객체의 내부 작동에 직접 접근하는 것을 제한하여 데이터의 무결성을 보호합니다. 이는 "쓰기 쉽고 부작용을 줄이는" 코드를 만드는 데 기여합니다.
자바는 접근 제어자(Access Modifier)를 통해 캡슐화를 구현합니다.
Modifier | Class (클래스 내) | Package (패키지 내) | Subclass (하위 클래스) | World (전체) |
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
(default) | Y | Y | N | N |
private | Y | N | N | N |
- public: 어디서든 접근 가능합니다.
- protected: 같은 패키지 내 또는 상속 관계에 있는 하위 클래스에서 접근 가능합니다.
- default (package-private): 아무런 접근 제어자를 지정하지 않으면 기본적으로 같은 패키지 내에서만 접근 가능합니다.
- private: 해당 클래스 안에서만 접근 가능합니다.
일반적으로 멤버 변수는 private으로 선언하여 외부에서 직접 접근을 막고, public 메소드(게터/세터)를 통해 간접적으로 접근하도록 하여 캡슐화를 유지합니다.
3. 상속(Inheritance): 코드 재사용의 강력한 도구
상속(Inheritance)은 객체 지향 프로그래밍에서 한 객체 또는 클래스가 다른 객체 또는 클래스를 기반으로 하여 유사한 구현을 유지하는 메커니즘입니다. 이는 부모-자식 관계를 형성하여 코드를 재사용하고 확장하는 데 도움을 줍니다.
자바의 모든 클래스는 java.lang.Object 클래스를 암묵적으로 상속받습니다. Object 클래스는 모든 객체의 최상위 계층이며, 모든 객체는 이 클래스의 메소드를 구현합니다.
상속 예시: Animal과 Dog
- Animal 클래스 (부모 클래스 또는 슈퍼클래스)는 move(), eat()과 같은 일반적인 동물의 행동을 정의할 수 있습니다.
- Dog 클래스 (자식 클래스 또는 서브클래스)는 Animal 클래스를 상속받아 move()와 같은 행동을 물려받고, bark()와 같은 개만의 고유한 행동을 추가할 수 있습니다.
// 부모 클래스 (Superclass)
class Animal {
public void move() {
System.out.println("동물이 움직입니다.");
}
public void eat() {
System.out.println("동물이 먹이를 먹습니다.");
}
}
// 자식 클래스 (Subclass) - Animal을 상속받음
class Dog extends Animal {
public void bark() {
System.out.println("개가 멍멍 짖습니다.");
}
}
public class InheritanceExample {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.move(); // Animal 클래스에서 상속받은 move() 메소드 호출
myDog.eat(); // Animal 클래스에서 상속받은 eat() 메소드 호출
myDog.bark(); // Dog 클래스 자체의 bark() 메소드 호출
}
}
4. 메소드 오버라이딩 (Method Overriding): 부모의 행동을 재정의
메소드 오버라이딩(Method Overriding)은 객체 지향 프로그래밍의 한 기능으로, 하위 클래스(자식 클래스)가 이미 상위 클래스(부모 클래스)에 의해 제공된 메소드의 특정 구현을 제공하도록 허용합니다. 즉, 부모 클래스로부터 상속받은 메소드의 동작을 자식 클래스에서 자신의 필요에 맞게 변경하는 것을 말합니다.
java.lang.Object 클래스의 toString() 메소드는 모든 객체가 문자열 표현을 가질 수 있도록 기본 구현을 제공합니다. 하지만 이 기본 구현은 객체의 메모리 주소 등을 반환하므로, 객체의 실제 내용을 파악하기 어렵습니다. 이때 toString() 메소드를 오버라이딩하여 객체의 유용한 정보를 문자열로 반환하도록 만들 수 있습니다.
@Override 어노테이션:
자바에서 어노테이션(Annotation)은 자바 소스 코드에 추가될 수 있는 구문 메타데이터(syntactic metadata)의 한 형태입니다. 클래스, 메소드, 변수, 매개변수 및 자바 패키지에 애노테이션을 달 수 있습니다.
@Override 애노테이션은 컴파일러에게 "이 메소드는 상위 클래스의 메소드를 오버라이딩하는 것"임을 알려주는 역할을 합니다. 이는 오버라이딩 규칙을 제대로 지켰는지 검사하여 오류를 줄이는 데 도움을 줍니다.
메소드 오버라이딩 예시: toString() 메소드
Customer 클래스에서 Object 클래스로부터 상속받은 toString() 메소드를 오버라이딩하여 고객 정보를 보기 좋게 출력하도록 변경해 봅시다.
// Customer 클래스 (이전 예제에서 이어짐)
public class Customer {
private String name;
private String number;
private String email;
public Customer(String name, String number, String email) {
this.name = name;
this.number = number;
this.email = email;
}
// @Override 애노테이션을 사용하여 toString() 메소드 재정의
@Override // [cite: 185]
public String toString() { // [cite: 186, 188]
return "고객 정보: [이름: " + name + ", 전화번호: " + number + ", 이메일: " + email + "]";
}
// 다른 getter 메소드들... (생략)
public String getName() { return name; }
public String getNumber() { return number; }
public String getEmail() { return email; }
}
public class OverrideExample {
public static void main(String[] args) {
Customer customer = new Customer("박지민", "010-7777-8888", "park@example.com");
// 오버라이딩된 toString() 메소드 호출
System.out.println(customer.toString());
// 또는 객체를 직접 출력해도 toString()이 자동 호출됨
System.out.println(customer);
// 만약 부모 클래스(Object)의 toString() 결과를 보고 싶다면 super 키워드를 사용합니다.
// public String toString(){ return super.toString(); } [cite: 230]
}
}
이제 Customer 객체를 System.out.println()으로 출력하면 우리가 정의한 형식으로 고객 정보가 나타납니다.
4.1. super 키워드: 부모 클래스 멤버 접근
super 키워드는 하위 클래스에서 상위 클래스의 멤버(변수 또는 메소드)에 접근할 때 사용됩니다. 예를 들어, 오버라이딩된 메소드 내에서 부모 클래스의 원래 메소드를 호출하고 싶을 때 super.메소드이름() 형태로 사용합니다.
5. 정리
- 클래스는 객체의 설계도이며, 객체는 그 설계도를 통해 만들어진 실제 인스턴스입니다.
- 캡슐화는 데이터와 메소드를 묶고 외부 접근을 제어하여 코드의 안정성을 높입니다.
- 상속은 코드 재사용성을 높여 개발 시간을 단축하고 유지보수를 용이하게 합니다.
- 메소드 오버라이딩은 상속받은 메소드의 동작을 자식 클래스에서 재정의할 수 있게 하여 다형성(Polymorphism)을 구현하는 기초가 됩니다.
오늘의 실습
오늘의 느낀점
오버로딩과 오버라이딩의 차이! 오늘 드디어 오버라이딩을 다시 봤다. 확실히 처음배울때랑 한참 자바를 써보고 다시 한 번 정리하는 느낌이 다르다. 차곡차곡 지식이 다시 한번 쌓이는 느낌!
https://fastcampus.info/4n8ztzq
(~6/20) 50일의 기적 AI 환급반💫 | 패스트캠퍼스
초간단 미션! 하루 20분 공부하고 수강료 전액 환급에 AI 스킬 장착까지!
fastcampus.co.kr
'개발공부 > Java' 카테고리의 다른 글
패스트캠퍼스 환급챌린지 21일차 : 한 번에 끝내는 컴퓨터 공학 & 인공지능 복수전공 초격차 패키지 강의 후기 (2) | 2025.07.21 |
---|---|
패스트캠퍼스 환급챌린지 20일차 : 한 번에 끝내는 컴퓨터 공학 & 인공지능 복수전공 초격차 패키지 강의 후기 (0) | 2025.07.20 |
패스트캠퍼스 환급챌린지 19일차 : 한 번에 끝내는 컴퓨터 공학 & 인공지능 복수전공 초격차 패키지 강의 후기 (0) | 2025.07.19 |
패스트캠퍼스 환급챌린지 17일차 : 한 번에 끝내는 컴퓨터 공학 & 인공지능 복수전공 초격차 패키지 강의 후기 (0) | 2025.07.17 |
패스트캠퍼스 환급챌린지 16일차 : 한 번에 끝내는 컴퓨터 공학 & 인공지능 복수전공 초격차 패키지 강의 후기 (0) | 2025.07.16 |