본문 바로가기
Dev/☕ Java

[자바의정석 정리-2] 상속 inheritance, 오버라이딩, Super, Super()

by 아아덕후 2022. 5. 26.
반응형
목차
1. 상속
2. 부모 클래스와 자식 클래스
3. 클래스간의 관계
4. 클래스 관계 결정
5. 오버라이딩 , 오버로딩(간략)
6. Super
7. Super()

 


1. 상속

상속이란, 기존의 클래스재사용하여 새로운 클래스작성하는 것이다.

[장점]

-       보다 적은 양의 코드로 새로운 클래스를 작성할 수 있다.

-       코드를 공통적으로 관리할 수 있다.

-       코드의 추가 및 변경이 매우 용이하다.

 

[효과]

코드의 재사용성을 높이고 코드의 중복을 제거하여 프로그램의 생산성과 유지보수에 크게 기여한다.

 

출처 : https://techvidvan.com/tutorials/java-inheritance/

 


2. 부모 클래스와 자식 클래스 

 

조상 클래스 --> 기존작성클래스, 부모 클래스, 상위 클래스, 기반 클래스

자손 클래스 --> 새로 작성하고자 하는 클래스, 자식 클래스, 하위 클래스, 파생된 클래스

 

자손 클래스부모 클래스의 모든 멤버상속받는다.

자손 클래스부모 클래스의 멤버들을 포함한다.

 

Ex)

만약 부모 클래스에 A라는 멤버변수를 추가하면,

자손 클래스는 부모 클래스의 멤버를 모두 상속 받기 때문에

자손 클래스는 자동적으로 A라는 멤버변수가 추가된 것과 같은 효과를 얻는다.

 

반대로, 자손 클래스에 B라는 새로운 코드(멤버 변수 , 메서드 등)를 추가하면,

부모 클래스는 아무런 영향도 받지 않는다.

 

이를 통해 조상 클래스가 변경되면 자손 클래스는 자동적으로 영향을 받지만,

자손 클래스가 변경되는 것은 조상 클래스에 아무런 영향을 주지 못한다

 

이러한 특징으로 인해 상속이 거듭될수록 상속받는 클래스(자손 클래스)의 멤버 개수는 점점 늘어나게 된다.

 

이러한 의미로 상속을 받는 다는 것은 조상 클래스를 확장(‘extends’)한다는 의미로 해석할 수 있으며 이를 통해 상속에 사용되는 자바의 키워드가 extends인 이유라고 한다.

 

Class Parent { }

Class child extends parent {}

 

 

만약 A 부모 클래스에 A1A2 자식 클래스가 있을 때, A1A2에 같은 멤버변수를 추가해야한다면 각 자식 클래스(A1, A2)에 추가하는 것보다는 부모 클래스(A)에 추가하는 것이 좋다.

이를 통해 조상 클래스 하나만 변경하면 되므로 같은 내용의 코드를 한 곳에서 관리하며 코드의 중복을 줄일 수 있으며 유지보수를 용이하게 하며 및 일관성을 유지할 수 있다.

 

기존 클래스 (부모 클래스) Phone

 

 

새로운 클래스(자식 클래스) SmartPhone은 부모 클래스 Phone을 상속 받는다.

 

 

다음과 같이

자식 클래스인 SmartPhone 클래스는 부모 클래스인 Phone 클래스의 멤버변수를 사용할 수 있다.

 

 


 3. 클래스간의 관계

자손 클래스의 인스턴스를 생성하면 (SmartPhone sp = new SmartPhone() )

조상 클래스(Phone)의 멤버(power, call_time)와 자손 클래스의 멤버(lte)가 합쳐진 하나의 인스턴스로(sp) 생성된다. 

 

 

 

 

클래스간의 관계 포함관계

상속이외에도 클래스를 재사용하는 또 다른 방법은 클래스간에 포함(Composite)’관계를 맺어주는 것이다.

클래스 간의 포함관계를 맺어주는 것은 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수선언하는 것을 뜻한다.

 

 

 

한 클래스를 작성하는데 다른 클래스(Point)를 멤버변수로 선언하여 포함시키는 것은 좋은 생각이다.

하나의 거대한 클래스를 작성하는 것(Circle1)보다

단위별여러 개의 클래스작성한 다음, 이 단위 클래스들을 포함관계로 재사용하면

보다 간결한고 손쉽게 클래스를 작성할 수 있다.

 

위에서는 Circle1int x, int y를 직접 모두 작성하였다.

하지만 Circle2 클래스에서는 Point를 멤버변수로 선언하여 포함관계를 맺고 새로운 멤버변수 int r만 추가하였다.

x , y Point 클래스에서 관리한다.

이를 통해 Circle의 코드도 간결해지고 코드 관리에 수월하다.

 


 

4. 클래스 관계 결정

A : 부모 클래스

B : 자식 클래스

 

~ ~ 이다.  ( is – a ) : 상속 관계

~~을 가지고 있다. (has a ) : 포함관계

 

(Circle)은 점(Point)이다. (is a )

(Circle)은 점(Point)을 가지고 있다. (has a)

 

두번째 문장이 더 옳다는 것을 알 수 있다.

‘~ ~이다. (is a)’ 라는 문장이 성립한다면, 서로 상속관계를 맺어주고

‘~ ~을 가지고 있다. (has a)’ 라는 문장이 성립한다면 포함관계를 맺어주면 된다.

 

 

원은 도형이다.        --> is a : 상속

원은 도형을 가진다--> X

 

원은 점이다.        --> Is a  : X

원은 점을 가진다  --> has a  : 포함

 

또한 상속관계의 클래스에서

부모 클래스의 메서드 이름과 똑같은 메서드가 자식 클래스에 있을 경우

호출 시, 자식 클래스의 메서드호출되며 이를 오버라이딩이라고 한다.

 

[추가]

-  자바단일 상속만을 허용한다.

다중상속의 장점(복합적인 기능을 가진 클래스 쉽게 작성)도 있지만,

단점으로
1) 클래스간의 관계매우 복잡해진다는 점과

2) 상속받은 멤버간이름이 같은 경우 구별할 수 있는 방법없다는 단점이 있기 때문에 다중상속을 지원하지 않는다.

 

- 오브젝트 클래스

--> 모든 클래스 상속 계층도취상위에 있는 조상클래스.
다른 클래스로부터 상속받지 않는 모든 클래스들을 자동적으로 Object 클래스로부터 상속받게 한다.

만약, A클래스가 아무 클래스를 상속받지 않는다면 A 클래스는 자동적으로 Object클래스를 상속받는다.

만약, B클래스가 A클래스를 상속 받는다면, B클래스는 Object를 상속받지 않지만 ,
A
클래스가 Object 상속클래스를 상속받앗으므로 B클래스도 object클래스를 상속받은것과 마찬가지가 된다.

 


5. 오버라이딩, 오버로딩(간략)

조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것이다.

상속받은 메서드를 그대로 사용하기도 하지만, 자손 클래스 자신에 맞게 변경 해야하는 경우 조상의 메서드를 오버라이딩 한다.

→  메서드의 내용만을 새로 작성하는 것이기 때문에 메서드의 선언부는 조상의 것과 완전히 일치해야한다.

 [조건] 선언부가 서로 일치해야 한다.
1.
이름이 같아야 한다.
2.
매개변수가 같아야 한다.
3.
반환타입이 같아야 한다.

→  접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.

→  조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.

→  인스턴스 메서드 → static 메서드 / static 메서드 → 인스턴스 메서드 변경할 수 없다.

 

 

오버로딩 vs 오버라이딩.

 

오버로딩 : 기존에 없는 새로운 메서드 추가                              ( new)

오버라이딩 : 조상으로바부터 상속받은 메서드의 내용으 변경하는 것. (change , modify)

 

 


 

6. Super

-       객체 자신을 가리키는 참조변수이다.

-       인스턴스 메서드(생성자)내에만 존재한다. (static 메서드 내에 사용불가)

-       조상멤버자신의 멤버 구별할 때 사용한다. / (this: lviv 구별에 사용)

 

super는 자손클래스에서 조상클래스부터 상속받은 멤버를 참조하는데 사용되는 참조변수.

멤버변수와 지역변수의 이름이 같을 때, this를 붙여서 구별했듯이,

상속받은 맴버와 이름이 같을 때는 같은 이름으로 멤버변수가 존재하지만, super를 붙여 구별할 수 있다.

 

모든 인스턴스메서드에는 자신이 속한 인스턴스의 주소가 지역변수로 저장되며 이 주소가 참조변수인 thissuper의 값이 된다.

같은 이름의 멤버변수가 조상 클래스인 Parent에도 있고 자손 클래스인 Child 클래스에도 있을 때는 super.xthis.x는 서로 다른 값을 참조하게 된다.

 

super.x는 조상 클래스로부터 상속받은 멤버변수 x를 뜻하며,

this.x는 자손 클래스에 선언된 멤버변수를 뜻한다.

 

이처럼 조상 클래스에 선언된 멤버변수와 같은 이름의 멤버변수를

자손 클래스에서 중복해서 정의 하는 것이 가능하며,

참조변수 super을 이용해서 서로 구별할 수 있다. (만약, 조상 클래스에서 선언된 멤버변수의 이름이 자손 클래스에서 새로운 멤버변수로 선언하지 않았을 경우(중복되지 않았을 경우)에는 this.멤버변수 = super.멤버변수가 가능하다. )

 

또한 메서드 역시 super를 써서 호출할 수 있다.

특히 조상 클래스의 메서드를 자손클래스에서 오버라이딩한 경우에 super를 사용한다.

 

오버라이딩 시, 조상 클래스 메서드 내용에 추가적으로 작업을 덧붙이는 경우라면 ,

super을 사용해서 조상 클래스의 메서드를 포함시키는 것이 좋다.

 

왜냐하면, 후에 조상클래스의 메서드가 변경되더라도

변경 된 내용이 자손클래스의 메서드에 자동적으로 반영될 것이기 때문이다.(리팩토링 용의성)

 

 


7. Super()

-  super()는 조상 클래스의 생성자를 호출하는데 사용한다. 그림(2) 참고

n  조상의 생성자를 호출하는 경우에 사용하는 의미

(조상 클래스에서  의 생성자와 초기화블록은 상속이 되지 않기 때문)

-  생성자의 첫 줄에 반드시 생성자를 호출해야 한다!!!  그렇지 않으면 컴파일러가 생성자의 첫 줄에 조상의 기본 생성자 (super();)를 삽입한다.
→  하지만, 조상 클래스에서 기본 생성자로 선언하지 않았을 경우(매개변수 있는 생성자로만 선언했을 경우 컴파일 에러가 발생한다.)

-   조상의 멤버는 조상의 생성자를 호출해서 초기화한다.

-   참조변수 super와 상관이 없다. / super()생성자 이다.

 

그림(1) , 그림(2)

 

자손 클래스 생성자의 첫 줄에 반드시 조상 클래스의 생성자를 호출 한다.

따라서 조상 클래스에 기본 생성자를 추가 / 혹은 조상 클래스에서 선언한 생성자를

자손 클래스의 생성자 가장 첫 줄에 선언부에 맞게 super(x,y)를 통해 호출한다.

 

 

조상의 멤버는 조상의 생성자를 호출해서 초기화한다

조상 클래스에서 선언한 멤버변수는 조상 클래스에서 생성자를 만들고,

이후 자손 클래스에서 super()를 통해 해당 생성자를 호출함으로써 사용한다.

 

 

자손 클래스의 인스턴스를 생성하면,

[자손의 멤버][조상의 멤버]가 모두 합쳐진 [하나의 인스턴스]가 생성된다.

이로 인해 자손 클래스의 인스턴스가 조상 클래스의 맴버들을 사용할 수 있다.

 

따라서, 조상 클래스의 멤버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자가 호출 되어야 한다.

 

생성자의 첫 줄에서 조상클래스의 생성자를 호출해야 하는 이유는

자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있으므로

조상의 멤버들이 먼저 초기화 되어 있어 야하기 때문이다.

→  (조상 클래스 멤버 초기화 → 자손 클래스 인스턴스에서 조상 클래스 멤버 사용 가능)

 

인스턴스를 생성할 때는 클래스를 선택하는 것만큼 생성자를 선택하는 것도 중요하다.

 

참고 : https://www.youtube.com/watch?v=XT9KmsEk9f8&list=PLW2UjW795-f5JPTsYHGAawAck9cQRw5TD&index=24

 

 

 

 

 

반응형

댓글