Java/기본

[java] 상속의 개념 알아보기

vmpo 2020. 3. 21. 14:22

대충은 알고 있지만, 정확히는 모르고있었던 상속의 개념에 대해 정리해보겠습니다.

 

상속이란 자식 클래스가 부모클래스로부터 "능력"을 물려받는 것입니다. 여기서 능력이란 멤버변수, 메소드로 정의할 수 있겠습니다. 아래 내용에서는 이해를 쉽게하기 위해 능력으로 설명하겠습니다.

 

그럼 코드를 먼저 확인해보겠습니다.

 

extends 키워드로 상속 관계 만들기

 

아래와 같이 부모클래스인 Cafe 클래스를 생성하겠습니다. 멤버변수 name,location과 makeCoffee()라는 함수를 정의했습니다.

 

 

자식클래스는 Starbucks 클래스를 생성했습니다.

클래스명 옆에 extends 부모클래스명 을 입력해줍니다. 아직 Starbucks 내부에는 아무코드도 넣지 않았습니다.

 

 

부모-자식클래스의 관계

앞에서 상속을 받는 것은 능력을 물려받는 것이라고 언급했습니다. 

아래와 같이 Starbucks 타입(자료형)으로 Starbucks 객체를 선언했습니다.

 

starbucks. 으로 어떤 메소드, 멤버변수에 접근할 수 있는지 확인해보면, 아래와 같이 Cafe클래스의 모든 함수와 멤버변수에 접근 가능한 것을 알 수 있습니다.

 

 

이제 상속을 받으면 부모클래스의 능력을 그대로 물려받는 것을 알게되었습니다. 그럼 Starbucks클래스에 멤버변수와 메소드를 추가해 능력을 확장 시켜보겠습니다.

 

Starbucks클래스에 menu라는 멤버변수와 pay()라는 함수를 정의했습니다. 이제, Starbucks클래스는 Cafe클래스의 능력 + Starbucks클래스의 능력을 갖게 되었습니다.

 

 

Main함수에서 Starbucks클래스의 객체를 만들어 능력이 확장된 것을 확인해보겠습니다.

Cafe클래스의 모든 능력과, Starbucks클래스의 능력들이 모두 사용되는 것을 확인 할 수 있습니다. 

하나의 클래스를 선언하여 2개의 클래스를 사용하는 효과를 내고 있습니다.

 

 

 

상속을 받는경우에 만약 동일한 이름의 멤버변수나 메소드를 선언하면 어떻게 될까요?

아래 코드로 확인해보겠습니다.

 

Cafe와 Starbucks클래스에 test라는 동일한 이름의 변수를 선언해보았습니다.

출력했을때는 어떻게 될지 확인해보겠습니다.

 

 

출력결과는 아래와 같이 자식클래스의 name이 출력되게 됩니다.

같은 멤버변수를 선언했을때는 자식클래스의 멤버변수가 우선이 되는 것을 알 수 있습니다. 

 

메소드 오버라이딩

그럼 상속에서 중요한 개념인 메소드 오버라이딩에 대해 확인해보겠습니다.

 

오버라이딩은 부모클래스의 메소드를 자식클래스에서 변경해 사용 할 수 있음을 말합니다.

 

일단 상속받는 클래스는 아래와 같이 부모메소드들이 자동으로 정의되어 있습니다.

(@Override 어노테이션이 해당 메소드가 오버라이딩 되었다는 것을 알려줍니다.)

 

위에서 Starbucks클래스에는 아무 코드도 넣지 않고 않고 생성을 했었습니다. 아무것도 넣지 않더라도 내부적으로 아래와 같이 메소드들은 자동으로 정의가 됩니다. 이렇게 자동정의가 되기 때문에 따로 코드를 넣지 않아도 객체 생성후 부모클래스의 메소드들을 그대로 사용 할 수 있는 것입니다.

 

아래 오버라이드 메소드들에는 내부적으로 super.메소드명 으로 정의되어있습니다. super라는 키워드로 부모클래스의 특정 메소드를 접근하고 있는 것이라고 생각하시면 됩니다.

 

오버라이딩은 부모클래스의 메소드를 그대로 사용하는 것 뿐만아니라, 재정의해서 사용도 가능합니다.

makeCoffe() 메소드를 재정의해서 사용해보도록 하겠습니다.

 

아래와 같이 내부 메소드를 변경해보고 출력해보도록하겠습니다.

 

아래와 같이 출력해보면, 재정의한 메소드가 수행되는 것을 알 수 있습니다. 이처럼 상속관계에서 자식클래스가 부모클래스의 메소드를 재정의해서 사용하는 것을 오버라이딩이라고 합니다.

 

 

오버라이딩의 개념은 아래 페이지에서 좀더 자세히 정리해두었습니다.

 

[java] 오버로딩, 오버라이딩 (overloading, overriding)

어느언어에서나 중요한 개념인 오버로딩과 오버라이딩 개념을 확인해보겠습니다. 간단하게 개념은 아래와 같습니다. 기본개념 overloading : 같은 메소드명을 파라미터 또는 리턴 타입을 달리 하여 다르게 생성 할..

vmpo.tistory.com

 

상속관계에서 타입(자료형) 다르게 선언하기

상속관계에서 자식클래스 객체생성시 타입을 부모클래스로 정의할 수 있습니다.

아래와 같이 Cafe starbucks = new Starbucks(); 로 Starbucks객체를 생성이 가능합니다. 

이때 중요한 것은 이렇게 타입(자료형)을 Cafe로 선언한 경우에는 starbucks객체를 생성해도 Cafe의 능력을 한정된 다는 것입니다. 

즉 Starbucks클래스는 Cafe클래스 상속으로 능력이 확장되었지만, 실제 사용할 객체를 생성시에 Cafe 타입(자료형)으로 정의 할 경우 능력이 Cafe클래스의 능력으로 제한된다는 것입니다.

 

 

이때 중요한 것은 능력이 제한되었다는 것입니다.

즉 타입(자료형) = 껍데기 라고 생각해보면, 껍데기가 Starbucks가 아니라 Cafe기 때문에 Cafe의 겉모습을 하고 있지만 속은 Starbucks로 채운 것입니다. 

 

이상태에서는 기본적으로 Cafe클래스의 능력만 사용가능하고 Starbucks클래스의 능력은 사용이 불가합니다.

아래와 같이 Starbucks클래스에만 있는 pay()메소드와 menu 멤버변수는 오류가 발생하는 것을 알 수 있습니다.

 

Cafe와 Starbucks 클래스에 모두 선언되어있었던 test 변수의 경우 사용은 가능하지만, 출력하면 Cafe 클래스의 정의된 값으로 출력되게 됩니다.

 

test변수만 출력했을때

Cafe클래스의 능력을 모두사용해야 하지만, 앞서 설명했던 오버라이딩을 해서 메소드를 재정의하는 경우에는 

Starbucks클래스의 재정의한 메소드로 사용이 됩니다.

 

아래와 같이 출력해보면 재정의한 메소드가 출력되는 것을 알 수 있습니다. 

 

하지만, 자식클래스 타입(자료형)으로 부모클래스의 객체를 생성하는 방식은 불가능합니다.

 

Cafe 클래스는 애초에 Starbucks클래스보다 능력의 범위가 좁습니다. 시작이 작은 능력인 클래스의 객체를 더큰 범위의 타입(자료형)으로는 생성이 불가능하다는 것입니다. 

 

 

 

상속관계를 IS -A 관계라도고 하는데요. 자식클래스는 부모클래스다. 라는 문장은 성립하지만, 부모클래스는 자식클래스다 라는 개념은 성립이 되지 않습니다. 즉, Starbucks is a Cafe , 는 맞지만, Cafe is a Starbucks는 말이좀 이상합니다.

카페중에는 커피빈도 있고, 이디야도 있고 다양한 케이스가 있는데 카페는 스타벅스다라고 정의할 수는 없기 때문입니다.

 

결론적으로 부모클래스의 타입(자료형)으로 자식클래스의 객체는 사용이 가능하지만 이 반대는 불가합니다.

 

 

[정리]

1. 상속은 extends 키워드로 정의 할 수 있다.

2. 자식클래스는 부모클래스의 모든 멤버변수, 메소드를 물려받고

   자식클래스의 내부에서 멤버변수,메소드를 정의해 확장시켜 사용이 가능하다.

3. 부모클래스의 메소드를 자식클래스에서 재정의해서 사용하는 것을 오버라이딩이라고 한다.

 오버라이딩 할 경우, 오버라이딩된 메소드로 실행된다.

4. 부모클래스 타입(자료형)으로 자식클래스 객체를 생성하면, 부모클래스의 능력으로 제한된다.

   4-1. 위의 경우, 자식클래스에서 오버라이딩 한 메소드는 자식클래스의 메소드로 실행된다.

   4-2. 위의 경우, 자식클래스에서 정의한 멤버변수는 사용이 불가하다. 

5. 자식클래스 타입(자료형)으로 부모클래스의 객체를 생성할 수는 없다.

LIST