Java Study

TIL - 객체 지향 프로그래밍 (2)

초코너무조코 2024. 12. 30. 11:38
728x90

자바 상속, 제어자, 다형성, 추상 클래스, 인터페이스, 내부 클래스 공부 로그


1. 상속(Inheritance)

  • 개념: 부모 클래스의 필드와 메서드를 자식 클래스가 물려받는 것.
  • 키워드: extends
  • 특징:
    • 코드 재사용성을 높임.
    • 부모 클래스의 멤버를 자식 클래스에서 직접 사용하거나 오버라이딩 가능.

예제:

// 부모 클래스
class Animal {
    String name;

    void eat() {
        System.out.println(name + " is eating.");
    }
}

// 자식 클래스
class Dog extends Animal {
    void bark() {
        System.out.println(name + " is barking.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.name = "Buddy";
        myDog.eat();  // 부모 클래스의 메서드 사용
        myDog.bark(); // 자식 클래스의 메서드 사용
    }
}

2. 제어자(Access Modifiers)

  • 클래스, 필드, 메서드의 접근 범위를 지정.
  • 종류:
    1. public: 모든 클래스에서 접근 가능.
    2. protected: 같은 패키지 및 상속받은 클래스에서 접근 가능.
    3. default(패키지-프라이빗): 같은 패키지 내에서만 접근 가능.
    4. private: 해당 클래스 내에서만 접근 가능.

예제:

class Test {
    public int publicVar = 1;
    protected int protectedVar = 2;
    int defaultVar = 3;
    private int privateVar = 4;

    void display() {
        System.out.println("Private Variable: " + privateVar);
    }
}

public class Main {
    public static void main(String[] args) {
        Test obj = new Test();
        System.out.println("Public Variable: " + obj.publicVar);
        System.out.println("Protected Variable: " + obj.protectedVar);
        System.out.println("Default Variable: " + obj.defaultVar);
        // System.out.println(obj.privateVar); // 오류 발생 (private 접근 불가)
    }
}

3. 다형성(Polymorphism)

  • 개념: 하나의 참조 변수가 여러 객체의 메서드를 참조할 수 있는 능력.
  • 종류:
    1. 컴파일타임 다형성: 메서드 오버로딩.

    2. 1.1 컴파일타임 다형성 (Compile-time Polymorphism)
      • 메서드 오버로딩(Method Overloading)을 통해 구현됩니다.
      • 정의: 같은 이름의 메서드를 여러 개 정의하되, 매개변수의 개수, 타입, 순서를 다르게 작성하여 컴파일 시점에 어떤 메서드를 호출할지 결정합니다.
      • 특징:
        • 컴파일 시점에 메서드 호출이 결정됨.
        • 반환값만 다르게 정의하면 오버로딩이 성립되지 않음.

      1.2 런타임 다형성 (Runtime Polymorphism)
      • 메서드 오버라이딩(Method Overriding)과 업캐스팅(Upcasting)을 통해 구현됩니다.
      • 정의: 부모 클래스의 메서드를 자식 클래스에서 재정의하여, 실행 시점에 어떤 메서드가 호출될지 결정됩니다.
      • 특징:
        • 실행 시점에 동작이 결정됨.
        • 상속과 업캐스팅을 활용.
        • 부모 클래스의 참조 변수를 사용해 자식 클래스 객체를 참조(업캐스팅).
      예제: 메서드 오버라이딩과 업캐스팅의 효과:
      • 부모 타입의 참조 변수로 여러 자식 클래스 객체를 다룰 수 있음.
      • 동적 바인딩(Dynamic Binding)을 통해 실행 시점에 적합한 메서드를 호출.

      2. implements 키워드와 다중 상속

2.1 implements로 인터페이스 다중 구현 가능

  • 자바는 클래스의 다중 상속을 지원하지 않지만, 인터페이스는 다중 구현이 가능합니다.
  • implements 키워드를 사용하여 여러 인터페이스를 한 클래스에서 구현할 수 있습니다.

3. 요약 및 학습 포인트

  1. 다형성:
    • 컴파일타임 다형성: 메서드 오버로딩을 통해 구현. 호출할 메서드가 컴파일 시점에 결정됨.
    • 런타임 다형성: 메서드 오버라이딩과 업캐스팅을 통해 구현. 실행 시점에 호출할 메서드가 결정됨.
  2. implements와 상속:
    • 클래스는 다른 클래스를 하나만 상속(extends)할 수 있음.
    • 클래스는 여러 인터페이스를 implements를 통해 다중 구현 가능.
    • 클래스 상속과 인터페이스 구현을 함께 사용할 수 있음.

예제: 오버라이딩과 업캐스팅:

class Animal {
    void sound() {
        System.out.println("Some sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Bark");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Dog(); // 업캐스팅
        myAnimal.sound(); // Dog 클래스의 sound() 호출
    }
}

4. 추상 클래스(Abstract Class)

  • 개념: 객체를 생성할 수 없는 클래스. 공통 기능 정의와 함께 서브클래스에서 구현해야 할 메서드를 선언.
  • 키워드: abstract

특징:

  • 추상 메서드를 포함할 수 있다.
  • 추상 메서드는 선언만 하고 구현은 서브클래스에서 담당.

예제:

abstract class Animal {
    abstract void sound(); // 추상 메서드

    void eat() {
        System.out.println("This animal eats food.");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Bark");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.sound();
        myDog.eat();
    }
}

5. 인터페이스(Interface)

  • 개념: 클래스가 구현해야 하는 메서드의 청사진. 다중 상속을 지원하기 위해 사용.
  • 키워드: interface

특징:

  • 모든 메서드는 기본적으로 public abstract.
  • 필드는 public static final.
  • 한 클래스는 여러 인터페이스를 구현할 수 있다.

예제:

interface Animal {
    void sound();
}

interface Pet {
    void play();
}

class Dog implements Animal, Pet {
    @Override
    public void sound() {
        System.out.println("Bark");
    }

    @Override
    public void play() {
        System.out.println("Playing fetch");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.sound();
        myDog.play();
    }
}

6. 내부 클래스(Inner Class)

  • 개념: 클래스 내에 정의된 또 다른 클래스. 외부 클래스와 밀접한 관계를 가짐.
  • 종류:
    1. 인스턴스 내부 클래스: 외부 클래스 객체를 통해 접근.
    2. 정적 내부 클래스: 외부 클래스와 독립적으로 접근 가능.
    3. 로컬 내부 클래스: 메서드 내에서 정의.
    4. 익명 내부 클래스: 일회성 클래스 정의와 객체 생성.

예제:

class Outer {
    private String message = "Hello from Outer";

    class Inner {
        void display() {
            System.out.println(message);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner(); // 인스턴스 내부 클래스 접근
        inner.display();
    }
}

7. 배운 점

  1. 상속의 강력함: 부모 클래스의 코드 재사용 및 확장.
  2. 제어자의 중요성: 클래스 설계 시 데이터 캡슐화를 위한 접근 제한 설정.
  3. 다형성의 유용성: 코드 유연성과 확장성 향상.
  4. 추상 클래스와 인터페이스 비교: 추상 클래스는 공통 기능 구현을 포함하고, 인터페이스는 규격화에 초점.
  5. 내부 클래스 활용: 외부 클래스와 밀접하게 연결된 로직 캡슐화.

8. 추가 학습 계획

  • 람다식함수형 인터페이스를 내부 클래스와 비교.
  • 다형성 활용 예제와 디자인 패턴 적용.
  • 제어자와 함께 패키지 구조를 고려한 설계 연습.

이번 학습을 통해 자바 객체지향 프로그래밍의 핵심 개념을 더 깊이 이해하고 실습으로 체화할 수 있었다. 앞으로 프로젝트에 이를 적용하여 더욱 발전할 계획이닷!

728x90