[Day 4 | Java] 상속

y♡ding·2024년 10월 17일
0

데브코스 TIL

목록 보기
16/163

📌 상속(Inheritance)이란?

상속은 여러 클래스에서 공통적인 속성(필드)기능(메서드)을 부모 클래스에 정의하고, 이를 자식 클래스가 물려받아 사용하는 개념이다. 이를 통해 코드의 중복을 제거하고, 유지보수를 쉽게 하며, 재사용성을 높일 수 있다.

  • 상속은 상위 클래스(부모 클래스)의 멤버(필드, 메서드 등)를 하위 클래스(자식 클래스)가 물려받아 재사용할 수 있게 한다.
  • 자식 클래스는 부모 클래스에 정의된 모든 필드와 메서드를 사용할 수 있으며, 필요한 경우 부모 클래스의 기능을 확장하거나 수정할 수 있다.
  • 상속은 "A는 B의 일종이다"라는 관계("is-a" 관계)를 나타낸다. 예를 들어, CatAnimal의 한 종류이므로 Cat 클래스는 Animal 클래스를 상속할 수 있다.

🚨 부모와 자식 관계에서의 접근 권한

하지만, 부모 클래스의 모든 멤버를 물려받아도 접근 권한에 따라 자식 클래스가 직접 접근할 수 있는 멤버가 제한될 수 있다.

  • private 필드나 메서드는 자식 클래스에서 직접 접근할 수 없다.
  • default 접근 제한자는 상속받은 클래스가 다른 패키지에 있을 경우 접근할 수 없다.

이를 해결하기 위해 gettersetter 메서드를 사용하여 필드에 간접적으로 접근할 수 있다.


🤞🏻 상속의 주요 특징

  1. extends 키워드를 사용하여 상속을 구현한다.

    class 자식클래스 extends 부모클래스 {
        // 자식 클래스 코드
    }
  2. 자식 클래스는 부모 클래스의 메서드와 필드를 물려받는다.

    • 부모 클래스의 멤버는 자식 클래스에서 사용할 수 있지만, 부모 클래스는 자식 클래스의 멤버를 사용할 수 없다.
    • 자식 클래스는 부모 클래스의 멤버를 추가로 확장하거나 오버라이딩할 수 있다.
  3. 단일 상속만을 허용힌다.

    • 즉, 자식 클래스는 하나의 부모 클래스만을 상속받을 수 있다. 하지만, 하나의 부모 클래스는 여러 자식 클래스를 가질 수 있다.
  4. 코드의 중복성 제거

    • 자식 클래스가 부모 클래스의 기능을 재사용함으로써 코드 중복을 줄일 수 있다.
  5. 다형성 ⭐️

    • 상속은 다형성(polymorphism)을 구현하는 중요한 수단이다. 부모 클래스를 참조하는 변수로 자식 클래스의 객체를 가리킬 수 있다. 이는 프로그램이 유연하고 확장 가능하게 만들어 준다.

class Parent {
    String p = "parent";

    void viewParent() {
        System.out.println("viewParent() 호출");
    }
}

class Child2 extends Parent {
    String c2 = "child2";

    void viewChild() {
        System.out.println("viewChild2() 호출");
    }
}

class GrandChild1 extends Child2 {
    String gc2 = "grandChild2";

    void viewGrandChild() {
        System.out.println("viewGrandChild1() 호출");
    }
}

public class InheritanceEx01 {
    public static void main(String[] args) {
        GrandChild1 gc = new GrandChild1();
        gc.viewGrandChild();  // 자식 클래스의 메서드 호출
        gc.viewChild();       // 부모 클래스의 메서드 호출
        gc.viewParent();      // 조부모 클래스의 메서드 호출

        // 필드 접근
        System.out.println(gc.p);   // Parent의 필드 사용
        System.out.println(gc.c2);  // Child2의 필드 사용
        System.out.println(gc.gc2); // GrandChild1의 필드 사용
    }
}
  • 상속은 ParentChild2GrandChild1 순으로 계층 구조를 이루며, 자식 클래스는 상위 클래스의 모든 멤버를 상속받는다.
  • 자식 클래스는 부모 클래스와 조부모 클래스의 필드와 메서드를 사용할 수 있다.

🗣️ 호출 방법

class Parent {
    Parent() {
        System.out.println("Parent 생성자 호출");
    }

    void viewData1() {
        System.out.println("Parent viewData1() 호출");
    }
}

class Child1 extends Parent {
    Child1() {
        System.out.println("Child1 생성자 호출");
    }

    // 오버라이딩
    void viewData1() {
        System.out.println("Child1 viewData1() 호출");
    }
}

class Child2 extends Parent {
    Child2() {
        System.out.println("Child2 생성자 호출");
    }

    // 오버라이딩
    void viewData1() {
        System.out.println("Child2 viewData1() 호출");
    }
}

class Child3 extends Parent {
    Child3() {
        System.out.println("Child3 생성자 호출");
    }

    // 오버라이딩
    void viewData1() {
        System.out.println("Child3 viewData1() 호출");
    }
}

public class PolyMainEx05 {
    public static void main(String[] args) {
        
        // 1.
        Child1 c1 = new Child1();   
        Child2 c2 = new Child2();   
        Child3 c3 = new Child3();   

        c1.viewData1();
        c2.viewData1();
        c3.viewData1();
        
        
        // 2. 디형성 이용해서 호출
        Parent p = new Child1();
        p.viewData1();
        p = new Child2();
        p.viewData1();
        p = new Child3();
        p.viewData1();

        // 3. 배열
        Parent[] arr = new Parent[3];
        arr[0] = new Child1();
        arr[1] = new Child2();
        arr[2] = new Child3();
        arr[0].viewData1();
        arr[1].viewData1();
        arr[2].viewData1();
    }
}

✔️ is-a 관계와 has-a 관계

  1. 상속(Inheritance): "is-a" 관계

    • 상속을 통해 자식 클래스는 부모 클래스의 특성과 기능을 물려받아 사용한다. 자식 클래스는 부모 클래스의 특성을 "갖고 있는" 개념이므로 is-a 관계로 설명된다.
    • Cat is an Animal (고양이는 동물이다)
  2. 포함(Composition): "has-a" 관계

    • 포함은 클래스 내에서 다른 클래스의 객체를 멤버 변수로 포함하는 관계이다. 이는 상속과는 다르게 클래스 간의 소유 관계를 나타내며, 자바에서 재사용성을 높이는 방법 중 하나이다.
    • Car has an Engine (자동차는 엔진을 포함한다)

포함 관계

class Engine {
    void start() {
        System.out.println("Engine start");
    }
}

class Car {
    // Car 클래스는 Engine 객체를 멤버로 포함함
    private Engine engine = new Engine();

    void startCar() {
        engine.start();  // 포함된 Engine 객체의 메서드 호출
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.startCar();  // Engine의 start() 메서드 호출
    }
}

🤞🏻 포함(Composition)의 특징

  • 상속과 달리 포함 관계에서는 포함된 객체의 멤버에 접근하기 위해 해당 객체를 인스턴스화하고, 그 인스턴스의 메서드를 호출해야 한다.
  • 포함을 통해 유연한 구조를 만들 수 있다. 예를 들어, Car는 다양한 종류의 Engine을 가질 수 있으며, 새로운 Engine을 추가할 때 상속보다는 포함 관계가 더 적합할 수 있다.

  1. 상속(Inheritance)는 코드의 재사용성을 높이고, 다형성을 통해 프로그램의 유연성을 제공한다. 상속을 사용할 때는 단일 상속만 가능하지만, 부모 클래스의 멤버를 자식 클래스에서 물려받아 확장할 수 있다.

  2. 포함(Composition)은 상속과 달리 클래스 간의 소유 관계를 나타내며, 한 클래스가 다른 클래스를 포함하는 형태로 사용된다. 이를 통해 더 유연한 설계가 가능하며, 상속보다 더 낮은 결합도를 유지할 수 있다.

0개의 댓글

관련 채용 정보