코딩일기

[Java] 객체지향의 핵심 개념: 상속, 오버로딩, 오버라이딩, 하이딩

jhy_2023 2025. 1. 18. 20:48
728x90
반응형

📌 객체지향 프로그래밍의 주요 특징

객체지향 프로그래밍(OOP, Object-Oriented Programming)은 다음과 같은 네 가지 주요 특징을 가집니다:

1️⃣ 캡슐화(Encapsulation)

  • 데이터를 외부에서 직접 접근하지 못하도록 보호하고, 메서드를 통해 접근하도록 제어합니다.
  • 클래스 내부에 변수를 숨기고, getter와 setter 메서드로 접근할 수 있습니다.

2️⃣ 상속(Inheritance)

  • 부모 클래스의 속성과 메서드를 자식 클래스가 물려받는 것을 의미합니다.
  • 코드의 재사용성을 높이며, extends 키워드를 사용합니다.
  • 인터페이스implements 키워드를 사용하여 구현하며, 모든 메서드가 추상 메서드입니다.

3️⃣ 다형성(Polymorphism)

  • 같은 이름의 메서드가 객체에 따라 다르게 동작합니다.
  • 메서드 오버로딩과 메서드 오버라이딩으로 구현됩니다.

4️⃣ 추상화(Abstraction)

  • 객체의 공통된 특징만 추출하여 클래스를 설계합니다.
  • 인터페이스나 추상 클래스를 활용합니다.

📌 객체와 클래스

1️⃣ 인스턴스

  • 객체(Object): 현실 세계의 사물을 소프트웨어로 표현한 것. 예: 책, 자동차, 사람.
  • 클래스(Class): 객체를 생성하기 위한 설계도. 예를 들어, 자동차를 표현하는 클래스는 속성(색상, 모델)과 동작(주행, 정지)을 포함.
  • 클래스는 설계도, 객체는 설계도로 만든 실물입니다. 예를 들어, 설계도로 집(객체)을 지을 수 있듯이 클래스는 객체를 생성하는 틀입니다.
  • 인스턴스 : 객체를 메모리에 생성한 상태를 인스턴스라고 합니다.
// Car 클래스 정의 (객체 설계도)
class Car {
    String color; // Car 클래스의 속성 (멤버 변수)
    void drive() { System.out.println("Driving!"); } // Car 클래스의 동작 (메서드)
}

// Car 클래스의 객체 생성 (인스턴스화)
Car myCar = new Car(); // myCar는 Car 클래스의 인스턴스

위 코드는 Car라는 클래스를 정의한 후, 이를 기반으로 myCar라는 객체를 생성한 예입니다. Car 클래스는 설계도 역할을 하고, myCar는 그 설계도로부터 만들어진 실체(객체)입니다.

반응형

📌 속(Inheritance)

  • 상속은 부모 클래스의 속성과 메서드를 자식 클래스가 물려받는 개념입니다. 부모(부모 클래스)로부터 유산(속성 및 메서드)을 물려받는 자식(자식 클래스)과 비슷합니다.
  • 키워드:
    • extends → 클래스 상속
    • implements → 인터페이스 상속
class Parent {
    void print() { System.out.println("부모 클래스 메서드"); }
}

class Child extends Parent {
    void print() { System.out.println("자식 클래스 메서드"); } // 오버라이딩
}

public class Main {
    public static void main(String[] args) {
        Parent p = new Parent();
        p.print(); // 부모 클래스 메서드

        Child c = new Child();
        c.print(); // 자식 클래스 메서드
    }
}

📌 오버로딩(Overloading)과 오버라이딩(Overriding)

1️⃣ 오버로딩

  • 같은 이름의 메서드를 매개변수의 개수나 타입을 다르게 정의하는 것.
class Math {
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
}

2️⃣ 오버라이딩

 

  • 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것.
  • 상속 관계에서만 가능합니다.

 

class Parent {
    void display() { System.out.println("Parent 메서드"); }
}

class Child extends Parent {
    @Override
    void display() { System.out.println("Child 메서드"); }
}
  • Parent 클래스는 부모 클래스입니다. display()라는 메서드를 가지고 있으며, 이 메서드는 "Parent 메서드"라는 문자열을 출력합니다.
  • Child 클래스는 Parent 클래스를 상속합니다.
    • class Child extends Parent → extends 키워드로 상속을 표현.
  • Child 클래스는 Parent 클래스의 메서드인 display()를 오버라이딩(재정의) 했습니다.
    • @Override 어노테이션: 부모 클래스의 메서드를 자식 클래스에서 재정의할 때 사용. (컴파일러가 올바르게 오버라이딩되었는지 확인)
  • 자식 클래스의 display()는 "Child 메서드"라는 문자열을 출력합니다.
class P {
    void print() {
        System.out.println("아버지 print");
    }
}

class C extends P {
    @Override
    void print() {
        System.out.println("자식 print");
    }
}

public class Main {
    public static void main(String[] args) {
        P a = new P();
        a.print(); // 부모 클래스의 print() 호출 => "아버지 print"

        C c = new C();
        c.print(); // 자식 클래스의 print() 호출 => "자식 print"

        P p = new C();
        p.print(); // 부모 클래스 타입 변수로 자식 객체 생성 => "자식 print"
    }
}

 

  • P a = new P();:
    • a는 P 타입의 객체입니다. 따라서 P 클래스에 정의된 print() 메서드가 호출됩니다.
    • 출력: "아버지 print"
  • C c = new C();:
    • c는 C 타입의 객체입니다. C 클래스에서 오버라이딩된 print() 메서드가 호출됩니다.
    • 출력: "자식 print"
  • P p = new C();:
    • p는 P 타입의 변수이지만, new C()를 통해 C 객체가 생성됩니다. 실제 객체의 타입이 C이므로, C 클래스에 오버라이딩된 print() 메서드가 호출됩니다.
    • 출력: "자식 print"
    • 오버라이딩의 특징은 실제 객체의 타입에 따라 메서드가 결정된다는 점입니다.

 

728x90

📌 하이딩(Hiding)

하이딩(Hiding)은 오버라이딩(Overriding)과 비슷하지만, 정적(static) 메서드에서만 발생하는 현상입니다. 오버라이딩과 하이딩의 가장 큰 차이점은 정적 메서드인스턴스 메서드에서 각각 발생하는 방식에 있습니다. 

class Parent {
    // 부모 클래스의 정적 메서드
    static void display() {
        System.out.println("Parent의 display()");
    }
}

class Child extends Parent {
    // 자식 클래스에서 부모의 정적 메서드를 숨김
    static void display() {
        System.out.println("Child의 display()");
    }
}

public class Main {
    public static void main(String[] args) {
        // 부모 클래스의 메서드 호출
        Parent.display();  // 출력: Parent의 display()

        // 자식 클래스의 메서드 호출
        Child.display();   // 출력: Child의 display()

        // 부모 클래스를 참조하면서 자식 클래스의 정적 메서드 호출
        Parent p = new Child();
        p.display();       // 출력: Parent의 display() (하이딩 효과)
    }
}

 

  • Parent.display();
    • Parent 클래스의 display() 메서드가 호출됩니다.
    • 출력: "Parent의 display()"
  • Child.display();
    • Child 클래스의 display() 메서드가 호출됩니다.
    • 출력: "Child의 display()"
  • Parent p = new Child();
    • p는 Parent 타입의 변수입니다.
    • p가 new Child()로 초기화되어도, 정적 메서드는 참조 변수 타입에 따라 호출됩니다. 이 경우, p의 타입은 Parent이므로, Parent 클래스에 정의된 display() 메서드가 호출됩니다.
    • 하이딩이 정적 메서드에만 적용되며, 객체의 타입이 아니라 클래스의 타입에 따라 메서드가 호출된다
    • 출력: "Parent의 display()"

 

📌 스태틱 변수와 메서드

  • 스태틱(static)은 **"클래스 수준에서 공유"**된다는 개념을 가지고 있습니다. 즉, 스태틱 변수와 스태틱 메서드는 객체를 생성하지 않고도 클래스를 통해 직접 접근할 수 있다는 점이 특징입니다.

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

728x90
반응형