Day10_상속

2021. 10. 19. 14:30· Java/Java Fundamental
목차
  1. 📌 01. 상속(inherit)
  2. 📖 상속의 관계
  3. 📖 상속의 용어
  4. 📖 상속의 형식
  5. 📖 상속에서의 생성자
  6. 📖 부모 클래스 필드 생성자 호출
  7. 📖 생성자의 오버라이드

📌 01. 상속(inherit)


상속은 두 개 이상의 클래스가 어떠한 관계를 가지면서 상속을 맺게 되는 것이다.

따라서 상속이 뭔지 알기 전에 관계를 먼저 배워야 한다.

📖 상속의 관계

is - a 관계

Student라는 클래스와 Person이라는 클래스가 있다고 가정해보자.

위 문장에 이를 대입해보면

-> Student is a Person (학생은 사람이다.)

-> Person is a Student (사람은 학생이다.)

둘중 말이 되는 것은 첫 번째 문장이다.

학생은 사람이 맞지만 사람이라고 해서 전부 학생은 아니기 때문이다.

이때 앞에 오는 클래스가 자식 클래스가 되고 뒤에 오는 클래스가 부모 클래스가 된다.

상속은 대부분이 이 is-a 관계이다.

때문에 반드시 숙지를 하고 있어야 한다.

has - a 관계

Student이라는 클래스와 Pencil이라는 클래스가 있다고 가정해보자.

위 문장에 이를 대입해보면

-> Student has a Pencil (학생은 연필을 가지고 있다.)

-> Pencil has a Student (연필은 학생을 가지고 있다.)

둘중 말이 되는것은 첫 번째 문장이다.

이때 앞에 오는 클래스가 자식 클래스가 되고 뒤에 오는 클래스가 부모 클래스가 된다.

has-a 관계는 상속으로 표현이 가능하지만 보통 상속으로 표현하기 보단 이중 클래스로 표현한다.

📖 상속의 용어

위에서 부모 클래스와 자식 클래스라는 용어를 사용하였다.

  1. 부모 클래스 ( 슈퍼 클래스 )이 클래스는 다른 클래스에게 기능(method)를 제공한다.

  2. 자바에서의 표준언어는 '슈퍼 클래스'이다.

  3. 부모 클래스는 말 그대로 부모가 되는 클래스이다.

  4. 자식 클래스( 서브 클래스 )자바에서의 표준언어는 '서브 클래스'이다.sup의 p를 거꾸로 뒤집은 sub를 뜻해서 서브 클래스라고 칭한다.

  5. 이는 슈퍼 클래스의 Super를 줄여서 sup이라고 하는데

  6. 자식 클래스 다른 클래스에 기능(method)를 제공받는 클래스이다.

📖 상속의 형식

  1. 부모 클래스 ( 슈퍼 클래스 )
class (클래스명) {}
  1. 자식 클래스( 서브 클래스 )
class (클래스명) extends (슈퍼 클래스명) {}

이제 상속의 관계, 용어, 형태를 모두 배웠으므로 상속을 쓸 수 있다.

// 부모 클래스 (슈퍼 클래스)
public class Person {

    public void eat() {
        System.out.println("먹는다.");
    }

}
// 자식 클래스 (서브 클래스)
public class Student extends Person {

    public void study() {
        System.out.println("공부한다.");
    }
}
// 메인 클래스
public class MainClass {

    public static void main(String[] args) {

        // 슈퍼 클래스는 자신의 기능만 사용할 수 있다.
        Person p = new Person();
        p.eat();

        // 서브 클래스는 자신의 기능 + 상속 받은 기능을 사용할 수 있다.
        Student s = new Student();
        s.eat();    // 슈퍼 클래스의 eat메소드 사용!
        s.study();
    }

}

부모 클래스를 생성 후 자식 클래스를 생성하여 상속의 형태를 만들어 주었고 메인클래스에서 자식클래스를 통하여 부모 클래스와 자식 클래스의 모든 메소드를 사용하고 있다.

📖 상속에서의 생성자

자식은 부모가 없으면 존재할 수가 없다.

마찬가지로 자바에서 자식 클래스는 부모 클래스가 없으면 생성될 수 없다.

아래 코드를 보자.

// 부모 클래스 (슈퍼 클래스)
public class Person {

    // field
    private String name;

    // constructor
    public Person() {    // 디폴트 생성자
        name = "제시카";    
    }
    public Person(String name) {    // 필드 생성자
        this.name = name;
    }

    // method
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}
// 자식 클래스 (서브 클래스)
public class Student extends Person {

    // field
    public String school;

    // constructor
    public Student() {    // 디폴트 클래스
        school = "서강대학교";
    }
    public Student(String school) {    // 필드 클래스
        this.school = school;
    }

    // method
    public String getSchool() {
        return school;
    }
    public void setSchool(String school) {
        this.school = school;
    }

}
// 메인 클래스
public class MainClass {

    public static void main(String[] args) {

        // 1. 디폴트 생성자를 통한 객체 생성
        Student student1 = new Student();
        System.out.println(1.);
        System.out.println(student1.getName());
        System.out.println(student1.getSchool());

        // 2. 필드 생성자를 통한 객체 생성
        Student student2 = new Student("연세대학교");
        System.out.println(2.);
        System.out.println(student2.getName());
        System.out.println(student2.getSchool());
    }

}
[출력]
1.
제시카
서강대학교
2.
제시카
연세대학교

메인클래스에서 getSchool() 메소드의 경우는 자식클래스의 메소드이고

자식 클래스에 대한 객체를 만들었으므로 호출이 가능하다.

그렇다면 부모 클래스에 있는 getName() 메소드는

부모 클래스에 대한 객체도 만들어지지 않은 상태에서 어떻게 호출이 가능한 것일까?

이는 자식클래스에 있는 생성자가 자동으로 부모클래스에 있는 생성자를 호출하기 떄문에 가능한것이다.

디폴트 생성자든 필드 생성자든 상속으로 인한 부모 클래스가 존재하는 경우

부모 클래스의 생성자를 자동 호출한다.

위 코드에서

1번이 Student클래스의 디폴트 생성자가 Person클래스의 디폴트 생성자를 자동 호출한 경우이고

2번이 Student클래스의 필드 생성자가 Person클래스의 디폴트 생성자를 자동 호출한 경우이다.

생성자를 Source메뉴를 통하여 자동생성할때 super(); 라는 코드가 같이 생성되는 것을 볼 수 있다.

이때 이 super는 슈퍼 클래스의 super를 뜻하는 것이고

이는 "부모 클래스의 생성자를 호출합니다."라는 코드이다.

이때 이 super(); 라는 코드는 사용자가 적지 않아도

컴퓨터가 자동으로 호출하기 때문에 오류가 나지 않는다. (생략 가능)

결론

​ 메인 클래스에서는 보통 자식 클래스만을 다룬다.

​ 이때 메인 클래스는 위에서 설명했듯 부모 클래스의 생성을 반드시 필요로 한다.

​ 부모 클래스의 생성이 눈에 보이지 않더라도 자식클래스의 생성자를 호출할때

​ 자식 클래스의 생성자가 자동으로 부모 클래스의 생성자를 호출하고 있는 것이다.

📖 부모 클래스 필드 생성자 호출

위에선 부모 클래스의 디폴트 생성자만 호출하고 있다.

이 말은 다른 말로 부모 클래스의 필드값인 'name'은 바꿀수가 없다는 말이다.

Student클래스의 필드값인 school처럼 Person클래스의 필드값인 name도 지정해주려면 어떻게 해야 할까?

평소처럼 Person클래스의 setName() 메소드를 통하여

name 필드값에 값을 직접 넣어주면 해결이 가능한가?

그렇지 않다.

이유는 위 코드의 자식 클래스에선 부모 클래스의 디폴트 생성자만 호출하고 있고

디폴트 생성자는 단지 'name'이라는 필드값을 '제시카'라고 초기화를 시키는 기능을 가지고 있기 때문이다.

그렇다면 Student클래스의 필드값인 school뿐만 아니라

Person클래스의 필드값인 name도 지정해주려면 어떻게 해야 할까?

답은 Person클래스에 디폴트 생성자가 아닌 필드 생성자를 호출 하는 것이다.

// 자식 클래스에 생성자 하나 더 만들기
public Student(String name, String school) {
    super(name);    // 부모 클래스의 필드 생성자 호출!
    this.school = school;
}
// 메인 클래스에서 객체 생성 후 출력
Student student3 = new Student("티파니", "이화여대");
System.out.println(student3.getName());
System.out.println(student3.getSchool());

처음 코드에서 자식 클래스에 생성자만 하나 더 추가하고 메인 클래스에 객체 생성, 출력을 한 결과이다.

[출력]
티파니
이화여대

생성자가 달라진 점은 매개변수가 추가되었고

super(); 가 아닌 super(name);이 적혀있다는 것이다.

''클래스와 객체'' 때 배운 메소드의 오버로딩에서 함수의 바인딩을

정확히 인지하였다면 위 코드도 쉽게 이해가 가능하다.

과정

  1. 메인 클래스에서 name, school이라는 매개변수를 전달하였고
  2. 자식 클래스에선 자신의 필드값인 school은 그대로 반환을 해주면서 동시에 부모 클래스의 필드 생성자에 name을 매개변수로 전달한다.
  3. 부모 클래스에선 전달받은 매개변수를 통하여 필드값인 name을 자식 클래스에 반환한다.
  4. 자식 클래스는 부모 클래스에서 반환받은 name과 메인 클래스에서 전달받은 school을 그대로 반환해 준다.

📖 생성자의 오버라이드

자식 클래스는 부모 클래스의 기능을 상속받아 해당 메소드를 사용할 수 있다는 것을 배웠다.

하지만 부모 클래스의 메소드를 사용하면 안되는 경우가 있다.

아래 코드를 예시로 들어보자.

// 부모 클래스 (슈퍼 클래스)
public class Coffee {

    public void taste() {
        System.out.println("이빨에 끼는 맛");
    }    

}
// 자식 클래스 (서브 클래스)
public class Espresso extends Coffee {

}
// 메인 클래스
public class MainClass {

    public static void main(String[] args) {

        Espresso espresso = new Espresso();
        espresso.taste();

    }

}

(참고로 자식 클래스에는 아무런 코드가 적혀있지 않지만 "클래스와 객체"때 배운것을 토대로

디폴트 생성자가 생성되어 있다는 사실을 알고 있어야 한다.)

커피콩은 이빨에 끼는 맛이다.

에스프레소는 커피 콩의 맛과 같지 않다.

하지만 출력은 아래와 같다.

[출력]
이빨에 끼는 맛

Coffee클래스의 커피콩 맛이 아닌 Espresso의 에스프레소 맛을 출력하였지만

커피콩의 맛이 출력이 된다.

물론 설계를 통하여 바꿀 수 있지만 말 그대로 오버라이드의 학습을 위한 간단한 예시이다.

오버라이드는 이와 같은 경우에 자식 클래스에 생성함으로서 그 문제를 해결할 수 있게 해준다.

오버라이드는 규칙이 크게 두개가 있다.

  1. 오버라이드를 하고자 하는 부모 클래스의 메소드와 반드시 형태가 같아야 한다.(반환타입, 메소드명, 매개변수)
  2. 어노테이션(annptation)을 표시해줘야 한다. ( = @Override )
@Override
public void taste() {
    System.out.println("쓴 맛");
}

이러면 taste() 라는 메소드는 부모 클래스와 자식 클래스 두 곳 모두에 존재하게 된다.

이때 메인클래스에서 taste() 메소드를 호출하면 자식 클래스의 메소드가 호출하게 된다.

이를 '메소드의 오버라이드(override)'라고 부른다.

어노테이션(annotation) 이란?

​ 오버라이드 메소드를 생성하였을때 형태가 같은 함수인지를 확인해 주는 기능

​ 즉, 1번 규칙이 성립하는가를 확인해주는 기능을 한다.

​ 또한 코드에 "이 메소드는 오버라이드된 함수입니다." 를 알려주는 표시가 되기도 한다.

​ 안 적어도 오류가 나지는 않지만 이러한 편의성들을 위해서라도 반드시 적어줘야 한다.

저작자표시 비영리 변경금지 (새창열림)

'Java > Java Fundamental' 카테고리의 다른 글

Day12_컬렉션  (0) 2021.11.05
Day11_추상과 인터페이스  (0) 2021.11.01
Day09_클래스  (0) 2021.10.19
Day08_배열  (0) 2021.10.18
Day07_String  (0) 2021.10.18
  1. 📌 01. 상속(inherit)
  2. 📖 상속의 관계
  3. 📖 상속의 용어
  4. 📖 상속의 형식
  5. 📖 상속에서의 생성자
  6. 📖 부모 클래스 필드 생성자 호출
  7. 📖 생성자의 오버라이드
'Java/Java Fundamental' 카테고리의 다른 글
  • Day12_컬렉션
  • Day11_추상과 인터페이스
  • Day09_클래스
  • Day08_배열
ChoiJyun
ChoiJyun
ChoiJyun
ChoiJyun
ChoiJyun
전체
오늘
어제
  • 분류 전체보기 (87)
    • QC (11)
      • 용어 (4)
      • 개념 (4)
      • 설비 (2)
      • 인증 (1)
    • Java (19)
      • Java Fundamental (12)
      • JSP (7)
    • 데이터베이스 (1)
    • C# (25)
    • C, C++ (4)
    • Kotlin (5)
    • Andriod (13)
    • Git (7)
    • 오류 (1)

블로그 메뉴

  • 홈
  • 글쓰기
  • 관리
hELLO · Designed By 정상우.v4.2.2
ChoiJyun
Day10_상속
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.