🔌 SPARTA/Courses

객체지향 특징

eunjiom 2026. 1. 14. 20:46

✨ 캡슐화

1. 개념

  • 내부 내용 보호
  • 필요한 이유: 비밀, 개인정보 등 민감한 정보를 외부에 노출 X

2. 접근제어자

  • 클래스, 변수, 메서드, 생성자의 접근 범위를 제한
  • public, private 활용
더보기
public class Person {      // ✅ 외부에서 접근 불가 

    public String name;    // ✅ 외부에서 접근 불가 
    private String secret; // ❌ 외부에서 접근 불가 
    
    public Person() {}    // ✅ 외부에서 접근 불가 

    public void methodA() {}  // ✅ 외부에서 접근 가능
    private void methodB() {} // ❌ 외부에서 접근 불가
}
Person person = new Person(); // ✅ 접근가능 생성자가 public
person.name;                  // ✅ 접근가능 변수가 public
person.secret;                // ❌ 접근불가능 변수가 private
person.methodA();             // ✅ 접근가능 메서드가 public
person.methodB();             // ❌ 접근불가능 메서드가 private
  • 접근제어 입력 안 되어 있으면 기본값 = default

3. 게터(getter)와 세터(setter)

 

1) 게터(getter)

  • 데이터 간접 접근
더보기
public class Person { 
    private String secret;
    
    public String getSecret() {
		    return this.secret; // ✅ 객체의 secret 속성 반환
    }
}
public class Main {
    public static void main(String[] args) {
		    Person p1 = new Person();
		    p1.secret; // ❌ 직접 접근 불가능
		    String newSecret = p1.getSecret(); // ✅ 게터를 활용해 접근가능
    }
}

2) 세터(setter)

  • 데이터 간접 수정
  • 새로운 객체 생성
더보기
public class Person { 
    private String secret;
    
    public void setSecret(String secret) {
		    this.secret = secret; // ✅ secret 속성 설정 및 변경
    }
}
public class Main {
    public static void main(String[] args) {
		    Person p1 = new Person();
		    p1.secret = "password"; // ❌ 직접접근, 변경 불가능
		    p1.setSecret("newPassword"); // ✅ 세터를 활용해 접근, 변경가능
    }
}
  • 무분별한 세터 이용시 문제점
더보기
  • B 입력시 핵폭발 발생!
public class DataStore {
    String store;
}

DataStore dataStore = new DataStore();
dataStore.store = "B"; // ❌ 의문의 핵폭발 발생!

> 접근제어자 privatestore 보호 필요

public class DataStore {

    private String store; 
}

DataStore dataStore = new DataStore();
dataStore.store = "B"; // ❌ 컴파일 오류! 직접 접근 불가!

 > private 입력 시 직접 접근 불가 / 세터 추가하여 변경 필요

public class DataStore {
    private String store; 
    
    public void setStore(String data) {
        this.store = data;
    }
}

DataStore dataStore = new DataStore();
dataStore.setStore("B"); // ❌ 다시 핵폭발 발생!

 > 막아놨지만 B 입력 시 핵폭발 발생!

public class DataStore {
    private String store; 
    
    public void setStore(String data) {
        if ("B".equals(data)) {
            System.out.println("❌ 'B'는 입력할 수 없습니다!");
        } else {
		        this.store = data;
        }
    }
}

 > 오류 문구 출력으로 보호

✨ 상속

1. 개념

  • 클래스간의 관계 = 부모(상위), 자식(하위)
  • 재사용성, 확장 가능

2. 재사용성

  • 부모 클래스: 가문 소개 > extends 사용 > 자식 클래스가 물려받아 재사용 가능
더보기
public class Parent {
    public String familyName = "스파르탄";
    public int honor = 10;

    public void introduceFamily() {
        System.out.println("우리 " + this.familyName + " 가문은 대대로 명성을 이어온...");
    }
}
class Child extends Parent { // ✅ extends 키워드 활용
}
public class Main {

    public static void main(String[] args) {
        Child child = new Child();
        System.out.println(child.honor); // ✅ 부모의 속성을 물려받아 사용
        System.out.println(child.familyName); // ✅ 부모의 속성을 물려받아 사용
        child.introduceFamily(); // ✅ 부모의 메서드를 물려받아 사용
    }
}

3. super - 부모 인스턴스

  • 부모클래스의 멤버(변수, 메서드)에 접근할 때 사용하는 키워드
  • 자식 클래스에서 부모의 변수나 메서드를 명확하게 호출할 때 사용
public class Child extends Parent {

		private String familyName = "gim"

    public void superExample() {
        System.out.println("우리 " + this.familyName + " 가문은 ...");
        System.out.println("원래 가문의 이름은 " + super.familyName);
    }
}
  • super() : 부모 인스턴스의 생성자
더보기
  • 항상 생성자의 첫 줄
public class Child extends Parent {

		...

    public Child() {
        super(); // ✅ (1)부모클래스 생성자를 먼저 호출
        // 추가로직은 여기에 작성
    }
}
public class Parent {
    public Parent() {} // ✅ 부모 생성자
}

4. 확장

  • 부모 클래스 기능 유지 + 자식 기능 추가
더보기
public class Child extends Parent {

		...

		// ✅ 부모에는 없지만 자식에만 있는 기능
    public void showSocialMedia() {
        System.out.println("우리 가문은 이제 SNS도 합니다. 팔로우 부탁드려요!");
    }
}
public class Main {

    public static void main(String[] args) {
		    ...
        child.showSocialMedia(); // ✅ 부모에는 없지만 자식에만 있는 기능
    }
}

5. 메서드 오버라이딩: 재정의

  • 부모 메서드를 자식 클래스에서 변경하여 재정의
  • @Override  키워드 사용 (없어도 동작 O)
  • 메서드 이름, 매개변수, 반환타입이 완전히 동일
  • 접근 제어자는 부모보다 더 강한 수준으로만 변경 가능
더보기
public class Parent {

    // 기존 기능
    public void introduceFamily() {
        System.out.println("우리 " + familyName + " 가문은 대대로 명성을 이어온 가문입니다.");
    }
}
class Child extends Parent {
		...
    
    @Override
    void introduceFamily() { // ✅ 자식클래스에서 재정의
        System.out.println("오버라이드");
    }
}
public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.introduceFamily(); // 출력 "오버라이드"
    }
}

6. 추상클래스

  • abstract 키워드로 클래스 선언
  • 공통 기능을 제공하면서 하위 클래스에 특정 메서드 구현을 강제하기 위해 사용
  • 추상클래스로 객체를 생성X
더보기
public class Cat extends Animal {
    
    @Override
    void eat() {
        System.out.println("냠냠"); //  ⚠️ 자식클래스에서 강제 구현해야합니다.
    }
}
public class Main {

    public static void main(String[] args) {
        Animal animal = new Animal(); // ❌ 추상클래스는 구현할 수 없습니다.

        Cat cat = new Cat();
        cat.eat(); // ⚠️ 강제 구현한 메서드 사용
        cat.sleep(); // ✅ 부모클래스의 매서드 사용
    }
}
  • 추상클래스와 인터페이스의 차이

- 추상클래스: 계층적 구조 선언 / 공통 속성과 기능 재사용

- 인터페이스: 표준 제공 / 인스턴스 변수 선언x

 추상화

1. 개념

  • 불필요한 정보를 제거 /  본질적인 특징만 남기는 것
  • 추상화의 계층적 특징을 활용
  • 자바의 특징(인터페이스 상속, 클래스 상속) 구현

2. 인터페이스 상속을 활용한 추상 계층 표현

더보기
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();
    }
}

3. 클래스 상속을 활용한 추상 계층 표현

더보기
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();
    }
}

✨ 다형성

1. 개념

  • 하나의 타입 > 여러 객체를 다룰 수 있음

2. 인터페이스를 활용한 다형성

더보기
public interface LifeForm {

    void exist();
}
public interface Animal extends LifeForm {

    void makeSound();
}
public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("야옹");
    }

    @Override
    public void exist() {
        System.out.println("고양이가 존재합니다.");
    }

    public void scratch() {
        System.out.println("스크래치!");
    }
}
public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("야옹");
    }

    @Override
    public void exist() {
        System.out.println("고양이가 존재합니다.");
    }

    public void scratch() {
        System.out.println("스크래치!");
    }
}
public class Main {

    public static void main(String[] args) {

        // 다형성 활용
        Animal animal = new Cat();
        animal.exist(); // ✅
        animal.makeSound(); // ✅
    }
}

3. 형변환

 

1) 업캐스팅

  • 자식 타입 > 부모 타입
public class Main {

    public static void main(String[] args) {

        // 다형성 활용
        Animal animal = new Cat(); // ✅ 자동 형 변환
        animal.exist(); // ✅
        animal.makeSound(); // ✅
    }
}
  • 주의사항: 자식 고유기능 활용x
public class Main {

    public static void main(String[] args) {

        // 다형성 활용
        Animal animal = new Cat(); // ✅ 자동 형 변환
        animal.exist();
        animal.makeSound();
        animal.scratch(); // ❌ 사용 불가
    }
}

 

2) 다운캐스팅

  • 부모 타입 > 자식 타입 ( big > small )
public class Main {

    public static void main(String[] args) {

        // 다형성 활용
        Animal animal = new Cat();
        animal.exist();
        animal.makeSound();        
        Cat cat = (Cat) animal; // ✅ 다운캐스팅(부모Animal -> 자식Cat)
        cat.scratch(); // ✅ 자식 클래스의 기능 활용 가능
    }
}
  • 주의사항
더보기
  • 잘못된 다운캐스팅
public class Main {

    public static void main(String[] args) {
        // 다운 캐스팅
        Animal dog = new Dog();
        // 문법적으로 잘못된건 아니라서 에러가 발생하지 않습니다.
        Cat cat1 = (Cat) dog; // ⚠️ 
        cat1.scratch(); // ❌ 해당 라인이 실행할때만 에러 여부를 확인할 수 있습니다.
    }
}

 

  • instanceof  활용하여 해결
public class Main {

    public static void main(String[] args) {

        Animal animal2 = new Dog();

        // ✅ 안전한 다운캐스팅(animal2 가 Cat 의 인스턴스 유형인지 확인합니다.)
        if (animal2 instanceof Cat) {
            Cat cat = (Cat) animal2;
            cat.scratch();
        } else {
            System.out.println("객체가 고양이가 아닙니다.");
        }
    }
}

4. 장점

 

1) 한 가지 타입으로 유연한 프로그램 처리 가능

  • animal 안에 여러 자식 데이터 담기 가능
public class Main {

    public static void main(String[] args) {
        Animal[] animals = {new Cat(), new Dog()};
        for (Animal animal : animals) {
            animal.makeSound();
        }
    }
}

'🔌 SPARTA > Courses' 카테고리의 다른 글

걷기반 2회차: 배열(Array와 List)  (0) 2026.01.16
자바 개념 확장  (0) 2026.01.15
객체지향 이해하기  (0) 2026.01.09
Java 기초문법(2)  (0) 2026.01.08
Java 기초문법(1)  (0) 2026.01.08