목차
1. Chapter 2 - 7 : 객체지향 PART1 - 캡슐화(접근제어자)
1. 캡슐화
- 객체의 정보를 외부에서 직접 접근하지 못하게 보호하는 개념.
- 클래스 혹은 객체의 캡슐화는 접근 제어자를 통해 구현 가능.
* 캡슐화가 필요한 이유
- 외부에 노출하고 싶지 않은 정보를 캡슐화를 통해 보호하고 필요한 경우에만 안전하게 접근할 수 있도록 함.
- 캡슐화를 구현하려면 접근제어자에 대해 이해가 필요.
2. 접근제어자
- 클래스, 변수, 메서드, 생성자의 접근 범위를 제한하는 키워드.
- 캡슐화 구현을 위해 사용됨.

접근제어자 | 클래스 내부 | 패키지 내부 | 상속한 클래스 | 전체 공개 |
public | ✅ | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ✅ | ❌ |
default | ✅ | ✅ | ❌ | ❌ |
private | ✅ | ❌ | ❌ | ❌ |
접근제어자 활용 예시(public, private)
public class Person { // ✅ 외부에서 접근 가능
public String name; // ✅ 외부에서 접근 가능
private String secret; // ❌ 외부에서 접근 불가
public Person() {} // ✅ 외부에서 접근 가능
public void methodA() {} // ✅ 외부에서 접근 가능
private void methodB() {} // ❌ 외부에서 접근 불가
}
- 일단 private으로 시작하는 것이 좋음 → 데이터 보호 목적.
- 외부에 필요한 기능들만 public으로 바꿔서 노출해서 사용하는 것을 권장.
public class Person {
// 속성
private String name;
private String secret;
// 생성자
public Person(String name, String secret) {
this.name = name;
this.secret = secret;
}
// 기능
public void methodA(){}
public void methodB(){}
}
- 속성들은 객체가 만들어질 때 한 번 설정이 되면 변경될 일이 거의 없음.
- 속성이 private일 경우 생성자를 public으로 두고 public Person(String name, String secret) 이런 식으로 매개변수를 통해 생성 시점에 한 번에 받아서 객체에 대한 인스턴스 멤버들을 설정해주는 것이 더 효율적임.
- 생성 시점에 한 번 설정하면 그 다음에 외부에서 바꿀 수 없음.
3. 데이터 접근 - Getter/ Setter
- 캡슐화가 잘 적용된 클래스는 내부 데이터를 private으로 보호하고 있음.
- 데이터 조회나 변경이 필요한 경우 안전한 접근 방법 필요 → Getter/ Setter 메서드
* Getter 활용법
- 데이터를 안전하게 접근하기 위해 사용.
Person.java
public class Person {
private String secret;
public String getSecret() {
return this.secret; // ✅ 객체의 secret 속성 반환
}
}
Main.java
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.secret; // ❌ 직접 접근 불가능
String newSecret = p1.getSecret(); // ✅ 게터를 활용해 접근가능
}
}
* Setter 활용법
- 데이터를 안전하게 설정/ 변경하기 위해 사용.
Person.java
public class Person {
private String secret;
public void setSecret(String secret) {
this.secret = secret; // ✅ secret 속성 설정 및 변경
}
}
Main.java
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.secret = "password"; // ❌ 직접접근, 변경 불가능
p1.setSecret("newPassword"); // ✅ 세터를 활용해 접근, 변경가능
}
}
* 무분별한 세터란?
- 접근을 막아 놓고 다시 세터로 외부에 노출한다면 접근제어를 하는 의미가 사라짐 → 올바른 데이터만 저장할 수 있도록 제한.
- 접근제어자를 사용하거나, 세터를 사용하거나 결과값은 똑같게 되어서 의미가 없는 것이 무분별한 세터.
- 해결책 1: 접근제어자로 데이터 보호.
- 해결책 2: 세터 추가.
- 해결책 3: 안전한 데이터 설정 로직을 추가.
public void setStore(String store) {
if(store.equals("B")){
System.out.println("B가 입력되면 안됩니다.");
}else{
this.store = store;
}
}
위처럼 setter에 로직을 추가하는 방법이 있음.
2. Chapter 2 - 8 : 객체지향 Part2 - 상속
1. 상속(Inheritance)
- 클래스 간의 관계를 부모(상위), 자식(하위)로 바라보는 개념.
- 이 구조를 통해 상속에서는 재사용성, 확장 가능 → 물려받은 속성과 기능은 자식 클래스에서 재사용 또는 확장 가능.
- extends 키워드를 사용하여 상속관계 구현.
- 상속을 통해 코드 중복을 줄이고 유지보수성 높일 수 있음.
- 추상화, 다형성 구현에 활용됨.
* 상속의 장점
● 재사용성
- 부모 클래스의 내용을 물려받아 그대로 재사용 가능.
super() - 부모 인스턴스
- 부모 클래스의 멤버(변수, 메서드)에 접근할 때 사용하는 키워드.
- 자식 클래스에서 부모의 변수나 메서드를 명확하게 호출할 때 사용.
super() - 부모 인스턴스의 생성자
- 부모가 먼저 생성되고 자식이 생성됨.
- 부모자 먼저 생성되어야 하므로 super()는 항상 생성자의 첫 줄에 위치해야함 → 그 후에 추가 로직 작성!!
public class Child extends Parent {
...
public Child() {
super(); // ✅ (1)부모클래스 생성자를 먼저 호출
// 추가로직은 여기에 작성
}
}
- super(); 를 누르면 커서가 Parent 클래스의 생성자로 이동함.
* 확장
- 부모 클래스의 기능을 유지하면서 자식클래스에서 기능을 확장.
2. 메서드 오버라이딩(Overriding)
- 부모 메서드를 자식 클래스에서 변경하여 재정의하는 것.
- 오버라이드된 메서드에서는 @Override 키워드를 붙이는 것을 권장(없어도 동작함)
- @Override를 붙이면 컴파일러가 부모 클래스에 동일한 메서드가 없다고 경고를 줘서 실수 방지 가능.
- 메서드 이름, 매개변수, 반환 타입이 완전히 동일해야함.
- 접근 제어자는 부모보다 더 강한 수준으로만 변경 가능.
3. 추상 클래스
- 공통 기능을 제공하면서 하위 클래스에 특정 메서드 구현을 강제하기 위해 사용됨.
- 객체를 생성할 목적이 아니라 "설계도" 역할을 할 때 적합함.
- abstract 키워드로 클래스를 선언하면 추상클래스.
- 추상클래스로 객체 생성 불가.
- 일반 클래스처럼 변수와 메서드를 가질 수 있음.
예시)
Animal.java - 추상클래스
abstract class Animal {
private String name; // ✅ 변수선언가능
abstract void eat(); // ⚠️ 추상메서드: 상속 받은 자식은 강제 구현해야합니다.
public void sleep() { // ✅ 자식클래스에서 재사용가능합니다.
System.out.println("쿨쿨");
}
}
Cat.java
public class Cat extends Animal {
@Override
void eat() {
System.out.println("냠냠"); // ⚠️ 자식클래스에서 강제 구현해야합니다.
}
}
Main.java
public class Main {
public static void main(String[] args) {
Animal animal = new Animal(); // ❌ 추상클래스는 구현할 수 없습니다.
Cat cat = new Cat();
cat.eat(); // ⚠️ 강제 구현한 메서드 사용
cat.sleep(); // ✅ 부모클래스의 매서드 사용
}
}
⚠️ 추상클래스와 인터페이스 차이점
- 상속이 계층적 구조를 선언하기 적합함.
- 인터페이스는 표준을 제공하는 데 적합함.
- 인터페이스는 인스턴스 변수를 선언할 수 없음.
- 계층적 구조를 표현하면서 공통 속성과 기능을 재사용할 때 추상클래스를 사용하는 것이 적합함.
4. Object 클래스
- 모든 클래스는 Object를 상속받고 있음.
- equals() 같은 정의하지 않은 기능을 사용할 수 있었던 이유는 모든 객체는 Object 클래스를 상속받은 객체기 때문.
3. Chapter 2 - 9 : 객체지향 Part3 - 추상화
1. 추상화
- 불필요한 정보를 제거하고 본질적인 특징만 남기는 것.
- 객체지향 프로그래밍에서는 추상화의 계층적 특징을 활용해서 유지보수성이 좋은 프로그램을 만들 수 있음.
- 자바의 특징(인터페이스 상속, 클래스 상속)을 이용해 계층적 구조를 만들어왔음.
인터페이스 상속을 활용한 추상 계층 표현
public interface LifeForm {
void exist(); // ✅ 공통: 모든 생명체는 존재한다.
}
public interface Animal extends LifeForm {
void makeSound(); //✅ 공통: 모든 동물은 소리를 냅니다.
}
public class Cat implements Animal {
@Override
public void exist() {
System.out.println("고양이가 존재합니다.");
}
@Override
public void makeSound() {
System.out.println("야옹");
}
public void scratch() {
System.out.println("스크래치");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.exist();
cat.makeSound();
cat.scratch();
}
}
클래스 상속을 활용한 추상 계층 표현
public class LifeForm {
public void exist() {
System.out.println("존재합니다2"); // ✅ 공통: 모든 객체는 존재한다.
}
}
public class Animal extends LifeForm {
public void makeSound() {
System.out.println("소리를 냅니다2"); // ✅ 공통: 모든 생명체는 성장한다.
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("야옹2");
}
public void scratch() {
System.out.println("스크래치!");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.exist();
cat.makeSound();
cat.scratch();
}
}
[실습 과제]
💬 Q1. 스스로 주제를 정하고 인터페이스와 클래스를 활용하여 3단계 이상의 추상 계층을 구현해 보세요.
- 수업에서 배운 계층 구조와 동일하게 만들면 됩니다.
- 정답이 정해져 있지 않으니 자유롭게 상상하며 코딩해 보세요!
Perform.java(Interface)
package chapter2.abstraction.v3;
public interface Perform {
void perform();
}
Music.java(Interface)
package chapter2.abstraction.v3;
public interface Music extends Perform{
void sing();
}
Musical.java
package chapter2.abstraction.v3;
public class Musical implements Music{
@Override
public void perform() {
System.out.println("공연을 시작합니다.");
}
@Override
public void sing() {
System.out.println("노래를 부릅니다.");
}
public void act(){
System.out.println("연기를 합니다.");
}
}
Main.java
package chapter2.abstraction.v3;
public class Main {
public static void main(String[] args) {
Musical musical = new Musical();
musical.perform();
musical.sing();
musical.act();
}
}
'스파르타 내일배움캠프 > TIL(Today I learned)' 카테고리의 다른 글
25.03.07 TIL - 다형성 (2) | 2025.03.07 |
---|---|
25.03.06 TIL - 계산기 과제 회고 (2) | 2025.03.06 |
25.03.04 TIL - final, interface, Lv2. 계산기 과제 (3) | 2025.03.04 |
25.02.28 TIL - Wrapper Class, static, final, Interface (2) | 2025.02.28 |
25.02.27 TIL - 클래스, JVM 메모리, 계산기 과제 (2) | 2025.02.27 |