자바의 핵심 - 상속(1) 개념과 논리적 포함관계, 오버라이딩, 메서드 재정의와 가상메서드

Yeppi's 개발 일기·2022년 5월 20일
1

JAVA

목록 보기
16/27

1. 상속

1) 상속이란?

자식 클래스는 멤버변수와 메서드를 물려받아 확장(extends)한다

문법

class 자식클래스 extends 부모클래스 {  

}

클래스 상속과 재사용

  • 새로운 클래스를 정의 할 때
    이미 구현된 클래스를 상속(inheritance) 받아서 속성이나 기능을 확장하여 클래스 구현

  • 이미 구현된 클래스보다 더 구체적인 기능을 가진 클래스를 구현해야 할때 기존 클래스를 상속

  • 여러 클래스에 동일한 코드 반복
    → 유지보수 어렵기 때문에 재사용

  • 그러나, 무조건 코드의 재사용 때문에 상속을 하진 않음

extends 확장한다

  • 상속은
    단순히 똑같은 멤버 변수와 메서드를 물려받기만 하는 것 ❌
    자식 클래스에서 물려받은 멤버 변수와 메서드를 추가로 확장하는 것 ⭕

  • 키워드 뒤에 단 하나의 클래스만 올 수 있음
    → 모호성이 발생할 수 있기 때문
    👉 자바는 단일 상속(single inheritance)만을 지원함 (자세한 건 아래에서 설명)

  • 안전성을 기본으로 만든 언어가 JAVA


2) 단일 상속 VS 다중 상속

  • 자바는 단일 상속(single inheritance)만을 지원함
  • 다중 상속일 경우
    부모클래스의 변수이름이 동일할 때, 상속받는 자식클래스는 변수이름이 중복되는 문제점

단일 상속

class 자식클래스 extends 부모클래스1 {  

}

다중 상속

class 자식클래스 extends 부모클래스1, 부모클래스2 {  
	부모클래스1의 변수(a);
    부모클래스2의 변수(a);
}


3) 논리적 포함관계

상속은 '자식클래스 is a 부모클래스'

자식 클래스가 논리적으로 부모 클래스에 포함되어야 한다

IS-A 관계(is a relationship : inheritance)

  • 클래스들의 관계가 일반적인(general) 개념구체적인(specific) 개념과의 관계를 가질 때
    → 상속하기 GOOD!

  • 상위 클래스 : 하위 클래스보다 일반적인 개념 ex. Employee
    하위 클래스 : 상위 클래스보다 구체적인 개념들이 더해짐 ex. Engineer, Manager . . .

  • 상속은 클래스간의 결합도가 높은 설계
    → 상위 클래스의 수정이 많은 하위 클래스에 영향을 미칠 수 있음
    👉 계층구조가 복잡하거나 hierarchy(계층의 깊이)가 높으면 좋지 않음

HAS-A 관계(composition)

  • 클래스가 다른 클래스를 포함하는 관계
    → 변수로 선언
  • 상속하지 않음
  • 코드 재사용의 가장 일반적인 방법
  • ex. StudentSubject를 포함하는
    ex. Library를 구현할 때 ArrayList 생성하여 사용


🧐 상속 개념 정리 🧐

상위 클래스

  • 하위 클래스 보다 더 일반적인 개념과 기능을 가짐

하위 클래스

  • 상위 클래스 보다 더 구체적인 개념과 기능을 가짐
  • 상위 클래스의 속성과 기능을 확장 (extends)

상속을 구현 하는 경우

  1. 좀 더 기능이 많고 + 구체적이야할 때
    ⇒ 기존 클래스를 상속 받음

  2. 같은 스타일의(결이 같은) 클래스인데, 상속 받는 클래스는 좀 더 구체적인 것
    사람 extends 포유류

  1. 상속을 활용한 클래스 구현할 때

    • 한 클래스 안에, if~else 가 너무 많다면?
      상속을 고려해봐야함

    • 유지보수, 새로운 추가 사항 수정시 계에에속 추가 해야되는 불편함
      ⇒ 클래스의 단일성이 떨어짐

    • 상위클래스에서는 접근 못하지만
      하위클래스에서는 접근 가능하도록 protected
      (자세한 건 아래에서 설명)

👉 첫 설계에서 뼈대를 만들고 + 다양한 확장이 필요할 때, 상속을 유용하게 사용하기!



🍑 용어 🍑

  • 상속하는 클래스
    상위 클래스, parent class, base class(주로 c++), super class
  • 상속받는 클래스
    하위 클래스, child class, derived class, subclass


2. 오버라이딩 Overriding

하위 클래스에서 동일한 이름의 변수와 메서드를 재정의

1) 변수 오버라이딩

  • 부모의 멤버변수를 자식 클래스에서 오버라이딩하면?
    ⇒ 부모의 변수는 상속되지 않음

예시

class A {  
	String sNum;
    int iNum
    
    public void printInfo() {
		System.out.println("사과는 과일이다");
	}

}
class Apple extends A {  
	// sNum, iNum 은 상속 받음
	String apple; 
    
    // 오버라이딩 // 상속 받지 않음
    public void printInfo() {
		System.out.println("사과는 과일이 아니다");
	}
}


2) 메서드 오버라이딩

  • 부모클래스의 메소드를 자식 클래스에서 오버라이딩하면?
    부모의 메소드가 상속되지 않음

사용하는 상황

  1. 상위 클래스에 정의된 메서드 구현 내용 ≠ 하위 클래스에서 구현할 내용

  2. 상속을 받았다고 해서 모든 것을 그대로 쓰진 않기 때문 ⇒ 재정의 하여 구현

예시

class A {  
	String aNum;
}
class Apple extends A {  
	String aNum; // 상속 X
}


3) @Override 어노테이션

개념

  • 애노테이션 = 주석

  • 컴파일러에게 특별한 정보를 제공해주는 역할

  • 필요한 경우 사용자가 재정의해서 쓸 수 있음

종류

@Override

  • 재정의된 메서드
  • 선언부가 기존의 메서드와 다른 경우 에러가 남

@FunctionalInterface

  • 함수형 인터페이스

@Deprecated

  • 이후 버전에서 사용되지 않을 수 있는 변수
  • 메서드에 사용

@SuppressWarnings

  • 특정 경고가 나타나지 않도록 함
  • ex. @SuppressWarnings("deprecation") → @Deprecated가 나타나지 않도록 함



🧐 상속과 접근 제한 🧐

  • 부모 클래스에 선언한 private 멤버변수와 메소드
    ⇒ 자식 클래스로 상속되지 않음 ❌

  • 메소드 오버라딩에서 부모의 접근제한보다 자식의 접근제한 범위가
    확대되는 것은 가능 ⭕
    축소되는 것은 안됨 ❌

접근제한 범위가 궁금하다면?
Java 시리즈의 접근 제어 지시자 페이지를 참고해주세요



📌 실습 📌

@Override

  • calcPrice() 이름이 바뀌면 오류 뜸
    @Override
	public int calcPrice(int price) {
		return super.calcPrice(price);
	}

오버라이딩 메소드 자식 클래스에서 만들기

// 부모 클래스
public int calcPrice(int price) { // price 고객이 지불해야될 값
		bonusPoint += price * bonusRatio;
		return price; 
	}

// 자식 클래스
@Override
public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		price -= (int)(price * salesRatio); // 소수점일 수 있으니까 (int)로 처리
		return price;
	}


🍑 Overloading vs Overriding 🍑

오버로딩

  • 하나의 클래스 내에 동일한 이름의 메소드가 존재하는 것
  • 메소드 이름은 동일
  • 매개변수의 개수 또는 타입이 다름

오버라이딩

  • 상속 구조
  • 부모의 메소드와 동일한 시그니처를 가진 메소드가 자식 클래스에 재정의되는 것
  • 메소드 이름은 동일
  • 매개변수의 개수 또는 타입도 동일

예시

  • 부모클래스의 메서드
    public void printInfo() {
		System.out.println("사과는 과일이다");
	}
  • 자식클래스의 메서드 오버로딩
    public void printInfo(String fruit) { // 메서드 이름만 동일
		System.out.println( + fruit + "는 과일이다");
	}
  • 자식클래스의 메서드 오버라이딩
	int number;
    public void printInfo() { // 메서드 이름 동일 + 매개변수 개수 및 타입 동일
		System.out.println("사과는 과일이고, " + number + "개가 있다");
	}


3. 메서드 재정의와 가상 메서드

1) 자바는 모든 메서드가 가상 메서드다

instruction set

  • 명령어 집합(instruction set; 인스트럭션 셋)

  • 함수가 호출이 된다는 것 = instruction set 이 호출 된다는 것

  • 수행하는 기능(set)이라는 부분은?
    instruction 마다 메모리가 따로 생기지 않음

  • 인스턴스마다 stack 이나 heap 이 따로 생기거나, 함수가 따로 호출되는 것은?
    → 변수의 영역

👉 instruction set 과 함수가 차지한 영역은 각기 다르다

👉 instruction set 은 로직만 가지고 있다


🧐 메서드와 가상 메서드 정리 🧐

메서드(=함수의 일종)의 이름은?

  • 주소값을 나타냄

메서드는 명령어의 set

  • 프로그램이 로드되면?
    → 메서드 영역(코드 영역)에 명령어 set 이 위치

  • 해당 메서드가 호출 되면?
    → 명령어 set 이 있는 주소를 찾아 명령어가 실행됨

메서드에서 사용하는 변수들은 (메서드와 다른 메모리인) 스택 메모리에 위치

  • 다른 인스턴스라도 같은 메서드의 코드는 같음
    → 같은 메서드가 호출됨

  • 인스턴스가 생성되면 변수는 힙 메모리에 따로 생성되지만,
    메서드 명령어 set 은 처음 한번만 로드 됨



2) 예시

public class TestMethod {

	int num;
	
	void aaa() {
		System.out.println("aaa() 호출");
	}
	
	public static void main(String[] args) {
		
		TestMethod a1 = new TestMethod();
		a1.aaa();
		
		TestMethod a2 = new TestMethod();
		a2.aaa();
	}

}

  • 스택 메모리
    main 함수가 차지하는 영역은 코드 영역이 아니라 ‘지역변수’가 차지함

  • 힙 메모리
    → 실제 인스턴스의 메모리

  • 메서드 영역
    → 출력을 위해 실행되는 메소드 영역

👉 이때 만약 변수가 필요하다면? 다시 스택 메모리에 변수가 잡힘



3) 가상 메서드의 원리

  • 가상 메서드 테이블(vitual method table)에서 해당 메서드에 대한 address를 가지고 있음

  • 재정의된 경우는 재정의 된 메서드의 주소를 가리킴

  • 함수 이름으로 호출되는 것이 아니라, 함수 이름이 가리키는 주소에 대한 table을 가리킴

  • 가상 메서드 테이블

    • 메서드와 메서드 주소 ⇒ 해당 메서드 영역을 가리킴

이 개념은 나중에 복습하면서 다시 살펴봐야겠다...

profile
imaginative and free developer. 백엔드 / UX / DATA / 기획에 관심있지만 고양이는 없는 예비 개발자👋

0개의 댓글