Archives
Recent Posts
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
관리 메뉴

개발도생's Blog

[10Days] Study_Inheritance 본문

개발자의 일기/Study

[10Days] Study_Inheritance

개발도생 2023. 3. 28. 10:53

상속(inheritance)이란?

기존의 클래스에 기능을 추가하거나 재정의하여 새로운 클래스를 정의하는 것을 의미한다.

 

이러한 상속은 캡슐화, 추상화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 요소이다.

 

상속을 이용하면 기존에 정의되어 있는 클래스의 모든 필드와 메서드를 물려받아,

 

새로운 클래스를 생성할 수 있다.

 

이때 기존에 정의되어 있던 클래스를 '부모 클래스(parent class)' 또는

 

'상위 클래스(super class)', '기초 클래스(base class)'라고도 부른다.

 

그리고 상속을 통해 새롭게 작성되는 클래스를 '자식 클래스(child class)' 또는

 

'하위 클래스(sub class)', '파생 클래스(derived class)'라고도 한다.

// 부모 클래스
public class Parent {
	
	private int number = 1;

	public int getNumber() {
		return this.number;
	}
	
	public void setNumber(int number) {
		System.out.println("부모의 setNumber Method 동작 시작");
		this.number = number;
		System.out.println("부모의 setNumber Method 동작 끝");
	}
}
// 부모 클래스의 기능을 상속 받은 자식 클래스
// 자식 클래스의 이름 옆에 'extends 부모 클래스 이름'을 선언해주면 된다.
public class Child extends Parent{
	
	
	public void printNumber() {
		setNumber(3);
		System.out.println(getNumber());
	}
	
	@Override
	public void setNumber(int number) {
		System.out.println("자식의 setNumber Method 동작 시작");
		super.setNumber(number);
		System.out.println("자식의 setNumber Method 동작 끝");
	}

}
// 부모와 자식 클래스를 활용할 Main Class
public class Main {

	public static void main(String[] args) {
		/*
		 * 상속
		 *  - 클래스의 재사용성을 높여 줄 수 있다.
		 *  - 클래스 간에 공통 코드를 작성하여 관리하기 때문에 코드의 추가 및 변경이 용이(유지보수가 쉬워진다.)
		 *  - 코드의 중복을 제거하여 프로그램의 생산성/유지 보수에 기여
		 *  
		 *  - 부모 클래스, 자식 클래스로 나뉘어서 사용하며, 이 때 자식 클래스가 부모 클래스를 상속해서 사용할 수 있다.
		 *  - 부모 클래스를 상속한 자식은 부모가 가지는 멤버 변수, 멤버 메서드, 생성자를 그대로 사용할 수 있다.
		 *  - 상속을 사용할 때 자식 클래스에서 extends 키워드로 부모 클래스를 지정하여 생성한다.
		 *  
		 *  - 부모 클래스에서 멤버 변수의 접근 제한자가 'private'일 때, 자식 클래스에서는 접근이 어렵다.
		 *  - 부모 클래스의 private 멤버 변수를 간접적으로 접근하기 위해 getter/setter를 활용해야 한다.
		 *  
		 *  - 클래스 간의 관계가 다중 상속보다 명확하고 신뢰성 있는 코드 작성
		 *  - 자바에서는 다중 상속 미지원 -> 단일 상속만 지원
		 */
		
		Child child = new Child();
		
		child.printNumber();

	}
}

출력 값

 

상속의 장점은 무엇인가?

1. 기존에 작성된 클래스를 재활용할 수 있습니다.

 

2. 자식 클래스 설계 시 중복되는 멤버를 미리 부모 클래스에 작성해 놓으면,

자식 클래스에서는 해당 멤버를 작성하지 않아도 됩니다.

 

3. 클래스 간의 계층적 관계를 구성함으로써 다형성의 문법적 토대를 마련합니다.

 

아래의 그림은 부모 클래스와 자식 클래스 간의 포함 관계를 표현한 그림이다. 

TCP School 상속, 참고 이미지

이처럼 부모 클래스는 자식 클래스에 포함된 것으로 볼 수 있다.

 

따라서 부모 클래스에 새로운 필드를 하나 추가하면,

 

자식 클래스에도 자동으로 해당 필드가 추가된 것처럼 동작한다.

 


Object Class란,

자바에서 'Object Class'는 모든 Class의 부모 클래스가 되는 클래스다.

 

따라서 자바의 모든 클래스는 자동으로 Object 클래스의 모든 필드와 메서드를 상속받게 된다.

 

즉, 자바의 모든 클래스는 별도로 extends 키워드를 사용하여 Object 클래스의 상속을 명시하지 않아도

 

Object 클래스의 모든 멤버를 자유롭게 사용할 수 있습니다.

 

자바의 모든 객체에서 toString()이나 clone()과 같은 메서드를 바로 사용할 수 있는 이유가

 

해당 메서드들이 Object 클래스의 메서드이기 때문입니다.

import java.util.Objects;

public class Object {

	@Override
	public int hashCode() {
    	
	}

	@Override
	public boolean equals(Object obj) {
    
	}

	@Override
	public String toString() {
    	
	}
}

 


위 코드 예시들을 보면 '@Override'라는 어노테이션(Annotation)을 확인할 수 있다.

 

해당 어노테이션은 '오버라이딩'이라고 한다.

 

그렇다면 오버라이딩은 무엇인가?

 

오버라이딩, Overriding

오버로딩과 오버라이딩 너무 헷갈린다.

 

비슷한 듯 하지만 다른 것이기 때문에 숙지가 필수적이다.

 

먼저 오버로딩(Overloading)은, 하나의 이름을 가진 Method를 다양하게 활용할 수 있도록 하는 것이다.

 

오버라이딩(Overriding)은,  상속 관계에 있는 부모 클래스에서 이미 정의된 메서드를

 

자식 클래스에서 같은 시그니쳐를 갖는 메서드로 다시 정의하는 것이라고 할 수 있다.

 

오버라이딩이란, 상속받은 부모 클래스의 메서드를 재정의하여 사용하는 것을 의미합니다.

 

오버라이딩의 조건

오버라이딩은, 무작정 사용이 가능한 것은 아니다. 

 

몇 가지 조건을 살펴본다면,

 

1. 오버라이딩이란 메서드의 메서드의 동작만을 재정의하는 것이므로, 메서드의 선언부는 기존 메서드와 완전히 같아야 한다.

    하지만 메서드의 반환 타입은 부모 클래스의 반환 타입으로 타입 변환할 수 있는 타입이라면 변경할 수 있다.

 

2. 부모 클래스의 메서드보다 접근 제어자를 더 좁은 범위로 변경할 수 없다.

 

3. 부모 클래스의 메서드보다 더 큰 범위의 예외를 선언할 수 없다.

// 먼저 Main Class에서 자식 Class의 Method를 호출
public class Main {

	public static void main(String[] args) {
		
		Child child = new Child();
		
		child.printNumber();

	}
}
// 부모의 기능을 상속 받은 자식 Class
public class Child extends Parent{
	
	public void printNumber() {
		setNumber(3);	// 자식 setNumber Method에 매개 변수 값 입력
		System.out.println("오버라이딩 결과 값 : " + getNumber());	// 9번
	}
	
	
	@Override
	public void setNumber(int number) {
		System.out.println("자식의 setNumber Method 동작 시작");	// 1번
		super.setNumber(number);	// 2번, 입력 된 값으로 부모의 setNumber로 호출
		System.out.println("자식의 setNumber Method 동작 끝"); // 8번
	}

}
public class Parent {
	
	private int number = 1;
	
	public Parent() {
		
	}
	
	public Parent(int number) {
		this.number = number;
	}
	
	public int getNumber() {
		return this.number;
	}
	
	public void setNumber(int number) {
		System.out.println("오버라이딩 이전 부모 Class의 멤버 변수 값 : " + this.number);	// 3번
		System.out.println("부모의 setNumber Method 동작 시작");	// 4번
		this.number = number;	// 5번
		System.out.println("오버라이딩 이후 부모 Class의 멤버 변수 값 : " + this.number);	// 6번
		System.out.println("부모의 setNumber Method 동작 끝"); // 7번
	}
	
	
}

오버라이딩 결과 값

 


우리가 흔히 멤버 변수와 매개 변수의 이름이 같을 때 멤버 변수를 정의하기 위해 'this'를 키워드를 사용했었다.

 

여기 부모 Class의 Method나 Field 정의해 주기 위해서 사용하는 키워드 'super'라는 것도 알아둬야 한다.

 

 super 키워드란,

 부모 클래스로부터 상속받은 필드나 메서드를 자식 클래스에서 참조하는 데 사용하는 참조 변수다.

 

인스턴스 변수의 이름과 지역 변수의 이름이 같을 경우 인스턴스 변수 앞에 this 키워드를 사용하여 구분할 수 있다.

 

마찬가지로 부모 클래스의 멤버와 자식 클래스의 멤버 이름이 같을 경우 super 키워드를 사용하여 구별할 수 있다.

 

자바에서는 super 참조 변수를 사용하여 부모 클래스의 멤버에 접근할 수 있다.

 

super() Method

super() 메서드는 부모 클래스의 생성자를 호출할 때 사용된다.

 

자식 클래스의 인스턴스를 생성하면, 해당 인스턴스에는 자식 클래스의 고유 멤버뿐만 아니라

 

부모 클래스의 모든 멤버까지도 포함되어 있다.

 

따라서 부모 클래스의 멤버를 초기화하기 위해서는 자식 클래스의 생성자에서 

 

부모 클래스의 생성자까지 호출해야만 한다.

 

이러한 부모 클래스의 생성자 호출은 모든 클래스의

 

부모 클래스인 Object 클래스의 생성자까지 계속 거슬러 올라가며 수행됩니다.

 


상속에 대해서 공부를 했지만, 상속 하나만 가지고도 연관된 정보가 너무 많다는 것을 알았다.

 

상속을 사용하기 위해 어떻게 효율적으로 사용할 것인지,

 

동작 흐름과 참조 변수 사용 등 더 효과적이고 효율적으로 사용할 수 있도록 노력해야겠다.      

 

지금보다 더 나은 개발자가 되기 위해서 성실하게 공부해 보자.  

'개발자의 일기 > Study' 카테고리의 다른 글

[12Days] Study_Exception  (0) 2023.04.13
[11Days] Study_추상화  (0) 2023.04.07
[9Days] Study_Method  (0) 2023.03.24
[8Days] Study_Static&Constructor  (0) 2023.03.22
[7Days] Study_객체 지향 언어(Java)  (0) 2023.03.18
Comments