상속 (Inheritance)

jisoo·2022년 7월 11일
0

상속

목록 보기
1/2
post-thumbnail

상속이란 ? 👑

기존의 클래스를 재사용하여 새로운 클래스를 작성하는 자바의 문법 요소를 의미

  • 상위 클래스와 하위 클래스로 나누어 상위 클래스의 멤버(필드, 메서드, 이너 클래스)를 하위 클래스와 공유하는 것을 의미한다.

  • 하위 클래스는 상위 클래스가 가진 모든 멤버를 상속받는다.

  • 하위 클래스의 멤버 개수는 언제나 상위 클래스보다 같거나 많다.

  • 두 클래스 간 상속 관계를 설정할 때는 extends 키워드를 사용한다.

  • 자바에서는 단일 상속(single ingeritance) 만을 허용한다.

  • 인터페이스(interface)라는 문법 요소를 통해 다중 상속과 비슷한 효과를 낼 수 있는 방법이 존재한다.



상속 사용 시 장점

  • 코드를 재사용하여 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있어 코드의 중복을 제거 할 수 있다.

  • 상속은 다형적 표현이 가능하다.



상속예제

public class Person {
    String name;
    int age;

    void learn() {
        System.out.println("공부를 합니다.");
    }

    void eat() {
        System.out.println("밥을 먹습니다.");
    }
}

class Programmer extends Person { // Person 클래스로 부터 상속. extends 키워드 사용
    String companyName;

    void coding() {
        System.out.println("코딩을 합니다.");
    }
}


class HelloJava {
    public static void main(String[] args) {
        //Person 객체 생성
        Person p = new Person();
        p.name = "김코딩";
        p.age = 24;
        p.learn();
        p.eat();
        System.out.println(p.name);

        // Programer 객체 생성
        Programmer pg = new Programmer();
        pg.name = "박해커";
        pg.age = 26;
        pg.learn(); // Persons 클래스에서 상속받아 사용가능
        pg.coding(); // Programmer의 개별 기능
        System.out.println(pg.name);
    }
}

// 출력
공부를 합니다.
밥을 먹습니다.
김코딩
공부를 합니다.
코딩을 합니다.
박해커 




포함관계 💡

포함(composite)은 상속처럼 클래스를 재사용할 수 있는 방법으로, 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것을 의미한다.


포함관계 예시

class Employee {
    int id;
    String name;
    Address address;

    public Employee(int id, String name, Address address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }
    
    void showInfo() {
        System.out.println(id + " " + name);
        System.out.println(address.city + " " + address.country);
    }

    public static void main(String[] args) {
        Address address1 = new Address("서울", "한국");
        Address address2 = new Address("도쿄", "일본");
        
        Employee e = new Employee(1, "김지수" , address1);
        Employee e2 = new Employee(2, "박해커", address2);
        
        e.showInfo();
        e2.showInfo();

    }
}

class Address {
    String city;
    String country;

    public Address(String city, String country) {
        this.city = city;
        this.country = country;
    }

}
// 출력

1 김지수
서울 한국
2 박해커
도쿄 일본

  • 원래라면 Address 클래스에 포함되어 있는 인스턴스 변수 city와 country 를 각각 Employee 클래스의 변수로 정의해주어야 하지만, Address 클래스로 해당 변수들을 묶어준다음 Employee 클래스 안에 참조변수를 선언하는 방법으로 코드의 중복을 없애고 포함관계로 재사용하고 있다.

  • 클래스 간의 관계를 설정하는데 있어서 상속관계를 맺어 줄 것인지 포함 관계를 맺어 줄 것인지 판별 기준은

    • 클래스 간의 관계가 ~은 ~이다(IS-A) 인지 ~은 ~을 가지고 있다(HAS-A) 관계인지 문장을 만들어 생각해 보자.

    • 예시로 예를 들어보면, Employee 는 Address 이다. 라는 문장은 성립하지 않지만 Employee는 Address를 가지고 있다 는 어색하지 않기 때문에 상속보다는 포함관계가 적합하다.




메서드 오버라이딩

상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것을 의미한다.

예시

class Vehicle {

    void run() {
        System.out.println("Vehicle is running");
    }
}

class Bike extends Vehicle {
    void run() {
        System.out.println("Bike is running"); // 메서드 오버라이딩
    }

    public static void main(String[] args) {
        Bike bike = new Bike();
        bike.run();
    }
}

// 출력
"Bike is running"
  • 메서드 오버라이딩을 사용할 경우 3가지 조건을 만족시켜줘야 한다.

    • 메서드 선언부 (메서드 이름, 매개변수, 반환타입)이 상위클래스의 것과 완전히 일치해야 한다.
    • 접근 제어자의 범위가 상위 클래스의 메서드보다 같거나 넓어야 한다.
    • 예외는 상위 클래스의 메서드보다 많이 선언할 수 없다.

  • 오버라이딩을 사용할 경우 상위 클래스로 타입을 선언하고 각각 타입으로 객체를 생성해주면
    간편하게 배열로 선언하여 관리 할 수 있다는 편리성이 있다.

// 배열로 한번에 관리하기

Vehicle[] vehicles = new Vehicle[] { new Bike(), new Car(), new MotorBike()};
for (Vehicle vehicle : vehicles) {
		vehicle.run();
}

// 출력값
Bike is running
Car is running
MotorBike is running




super 키워드 , super( )

super 키워드는 상위 클래스의 객체 , super( ) 는 상위 클래스의 생성자를 호출 할 때 사용한다.


super 예제

class Super {

    public static void main(String[] args) {
        Lower l = new Lower();
        l.calNum();
    }
}

class Upper {
    int count = 20; // super.count
}

class Lower extends Upper {
    int count = 15; // this.count 

    void calNum() {
        System.out.println("count = " + count);
        System.out.println("this.count = " + this.count);
        System.out.println("super.count = " + super.count);
    }
}

// 출력
count = 15
count = 15
count = 20
  • 상속관계에서 서로의 인스턴스 변수의 이름이 같이 구분이 필요할 경우 그것을 구분할 방법이 바로 super 키워드 이다.



super( ) 예제

public class Test {
    public static void main(String[] args) {
        Student s = new Student();
    }
}

class Human {
    Human() {
        System.out.println("휴먼 클래스 생성자");
    }
}

class Student extends Human { 
    Student() {
        super(); // Human 클래스의 생성자 호출
        System.out.println("학생 클래스 생성자");
    }
}
  • super( ) 은 생성자 안에서만 사용가능하고, 반드시 첫 줄에 와야한다.
profile
Backend Developer 👩🏻‍💻

0개의 댓글