[JAVA 스터디] 6주차 : 상속

codename_hee·2021년 10월 28일
0

학습 목표

  • 자바 상속의 특징
  • super 키워드
  • 메소드 오버라이딩
  • 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
  • 추상 클래스
  • final 키워드
  • Object 클래스

1. 자바 상속의 특징

자바에서 상속이란 무엇인가?

  • 현실 세계에서 부모가 자식에게 재산을 '상속'한다고 하는 것처럼 객체 지향 프로그램에서도 부모가 자식에게 부모의 클래스나 메소드를 자식의 클래스에게 물려주는 경우를 상속이라고 한다.

자바 상속의 특징

  • 공통된 특징을 가지는 클래스에서 코드 중복을 줄여준다.
  • 부모 클래스의 멤버를 재사용하면서 자식 클래스는 간결해질 수 있다.
  • 클래스간의 계층적 분리를 도와주어 분류, 관리 상의 이점이 있다.
  • 부모 클래스는 Super Class이고 자식 클래스는 Sub Class이다.
  • 다중 상속을 지원하지 않는다. 즉, extends뒤에는 하나의 부모 클래스만 올 수 있다.
  • 상속 횟수에 제한이 없다.
  • 자바의 최상위 클래스는 'Object' 라는 클래스이다. 즉, 자바의 모든 클래스는 'Object'클래스의 자손이다.

상속 구현 방법

<자식 클래스의 부모 클래스 상속 방법>
class 자식 클래스 extends 부모클래스 {
}

<부모 클래스>
public class TV {
	멤버 변수 1;
    멤버 변수 2;
    메소드1;
}

<자식 클래스>
public class LG extends TV {
	String tvType;
}

2. Super 키워드

자바에서 자식 객체를 생성할 경우 부모 객체가 먼저 생성된 후 자식 객체가 생성된다.

super 키워드란?

  • 상속관계에서 자식 클래스가 부모 클래스의 멤버 변수나 메소드를 참조하기 위해 사용된다.
  • 자식 클래스에 부모 객체의 생성자를 임의로 지정하지 않았을 경우 자식 객체 생성시 컴파일러가 자동으로 'super()' 메소드를 통해 부모의 기본 생성자를 호출한다.
  • 만약 부모 클래스에 기본 생성자가 없고 매개 변수가 있는 생성자만 있다면 자식 생성자의 첫 줄에 반드시 부모 생성자 호출을 위한 super() 메소드를 명시적으로 작성해두어야 한다. 그렇지 않을 경우 컴파일 에러가 발생한다.

3. 메소드 오버라이딩

메소드 오버라이딩이란?

  • 자식 클래스에서 부모 클래스를 상속 받은 후, 부모 클래스에 정의되어 있는 메소드를 재정의하여 사용하는 것이다.
  • 부모 클래스 내의 특정 메소드는 자식 클래스에서 그대로 사용하기에 적합하지 않을 수 있기 때문에 보통 오버라이딩을 거쳐 부모 메소드를 사용하는 경우가 많다.
  • 메소드가 오버라이딩 되면 자식 객체에서 메소드가 호출될 경우 부모 객체의 메소드는 숨겨지고, 오버라이딩된 자식 메소드가 호출된다.

오버라이딩 규칙(@override 어노테이션 사용)

  1. 오버라이딩된 자식 클래스의 메소드는 부모의 메소드와 '메소드 이름, 매개 변수 조합, 리턴 타입'이 동일해야 한다.
  2. 접근 제한을 축소하여 오버라이딩 할 수 없다. 단, 반대는 가능하다.
    (부모 메소드가 public인데 자식 메소드가 private일 수는 없다는 의미)
  3. 새로운 예외를 throw할 수 없다.

4. 다이나믹 메소드 디스패치(Dynamic method dispatch)

메소드 디스패치란?

  • 자바는 런타임 시 객체를 생성하고 컴파일 시 생성할 객체 타입에 대한 정보만 보유한다.
  • 메소드 디스패치란 어떤 메소드를 호출할지 결정하여 실제로 실행시키는 과정이다.
  • 그 과정은 static(정적)/dynamic(동적) 두가지가 있다.

정적 디스패치(static dispatch)

  • 컴파일 시점에서 컴파일러가 특정 메소드를 호출할 것이라고 명확하게 알고 있는 경우
  • 컴파일 타임에 컴파일러, 사용자, 바이트코드 모두 어떤 메소드가 실행될 지 아는 것이다.
<코드예시>
<person 클래스>
public class Person{
	private int age;
    
    public void print() {
    	System.out.println("Hello");
    }
    
    public void print(String greeting) {
    	System.out.println(greeting);
    }
    
    public void printJob(){
    }
}

<main 클래스>
public class Main {
	public static void Main(String[] args) {
    	Person P = new Person();
        p.print();
        p.print("hi");
  	}
}

<출력결과>
Hello
Hi
  • 보통 오버라이딩한 메소드가 없을 경우, 상속받은 자식 클래스의 메소드가 아닐 경우에 대한 설명이지 않을까 개인적인 생각이다.
  • 함수를 오버라이딩하여 사용했을 경우에도 인자의 타입이나 리턴타입 등에 따라 어떤 메소드를 호출할 지 알 수 있는 경우

동적 디스패치(dynamic dispatch)

  • dynamic은 runtime의 동의어로 사용되며 dispatch는 어떤 메소드를 호출할지 결정하는 것이므로 런타임시에 호출할 메소드를 결정할 경우를 의미한다.
  • 컴파일러는 어떤 메소드를 호출할 지 모른다.
  • 인터페이스나 추상 클래스에 정의된 추상 메소드를 호출하는 경우
<Tv 클래스>
public class Tv {
	public void view() {
		System.out.println("티비를 보여줌");
	}
}

<Tv를 상속한 samsung 클래스>
public class Samsung extends Tv {
	
	@Override
	public void view() {
		System.out.println("OLED 티비를 보여줌");
	}
}

public class Main {
	public static void main(String[] args) {
		Tv tv = new Tv(); // Tv 참조 Tv 객체
		Tv samsungTv = new Samsung(); // Tv 참조, 삼성 객체
	
		tv.view(); //참조와 객체가 동일
		samsungTv.view();// 참조와 객체가 다름 (상속) => 다이나믹 메소드 디스패치
	}
}

=> 컴파일 시에는 참조 타입만 확인하고 런타임시 JVM(Java Virtual Machine)이 객체 타입을 파악하여 메소드를 실행시켜준다.

5. 추상 클래스

추상 클래스란?

  • 먼저 사전적 의미로 추상(abstract)은 실체 간의 공통되는 특성을 추출한 것을 말한다.
  • 이를 객체 지향 프로그래밍에 접목해보면, 객체를 직접 생성할 수 있는 클래스를 실체 클래스라고 했을 때, 이 클래스들의 공통적인 특성(즉, 필드와 메소드)을 추출해 선언한 클래스를 추상 클래스라고 할 수 있다.
  • 원론적으로는 하나 이상의 추상 메소드를 포함하는 클래스를 가리켜 추상 클래스라고 한다.
  • 추상 클래스와 실체 클래스는 '상속 관계'를 갖는다.
    - 추상 클래스가 부모, 실체 클래스가 자식 관계로 구현된다.
    • 따라서 실체 클래스는 추상 클래스의 모든 특성을 물려받고 추가적인 특성을 가질 수 있다.
      *특성 : 필드, 메소드

추상 클래스의 선언

클래스 선언에 abstract를 붙인다.

public abstract class 클래스 {
	//필드
    //생성자
    //메소드
}

추상 클래스의 특징

  • 일반 클래스처럼 필드, 생성자, 메소드를 선언할 수는 있지만 객체를 직접 생성해서 사용할 수는 없다. 따라서 new연산자를 통해 인스턴스 또한 생성하지 못한다.
  • 그러나 자식 객체가 생성될 때 'super()' 메소드를 호출하여 추상 클래스 객체를 생성하므로 추상 클래스 또한 반드시 생성자가 있어야 한다.
  • 추상 클래스를 상속받는 모든 클래스에서는 추상 메소드를 반드시 재정의해야 한다.
  • 추상 클래스는 새로운 실체 클래스를 만들기 위한 부모 클래스로만 사용된다. 즉, extends 뒤에만 올 수 있다.

추상 클래스의 용도

1. 실체 클래스들의 공통된 필드와 메소드의 이름을 통일하고자

  • 실체 클래스를 설계하는 사람들이 여러 명일 경우 실체 클래스마다 결국엔 공통된 역할을 하는 필드와 메소드가 여러번 선언되고 각기 다른 이름을 갖게 된다.
  • 이러한 상황에서 실체 클래스의 부모 클래스인 추상 클래스에서 공통된 필드와 메소드를 선언함으로써 각각의 실체 클래스에서는 추상 클래스의 필드 메소드를 상속받아 사용할 수 있다.
    => 코드에 통일성을 부여한다.

2. 실체 클래스를 작성할 시간을 절약하고자

  • 추상 클래스에 실체 클래스에서 사용될 필드와 메소드를 미리 만들어두고 실체 클래스마다 다른 점만 구현한다면 코드 작성 시간을 절약할 수 있게 된다.

3. 추상 메소드가 포함된 클래스를 상속받는 자식 클래스가 반드시 추상 메소드를 구현하도록 하기 위해

  • 일반 메소드를 상속받은 자식 클래스는 해당 클래스 내의 메소드를 구현할 수도, 안 할 수도 있다.
  • 그러나 추상 메소드가 포함된 추상 클래스를 상속받은 모든 자식 클래스는 추상 메소드를 구현해야만 인스턴스를 생성할 수 있으므로 반드시 구현하게 하고자 할 때 추상 클래스를 사용할 수 있다.

추상 메소드

  • 자식 클래스에서 반드시 오버라이딩 해야만 사용할 수 있는 메소드를 의미한다.
  • 선언부만이 존재하며 구현부는 작성되어 있지 않다.
  • 자식 클래스에서 작성되어 있지 않은 구현부를 오버라이딩하여 사용한다.
  • 추상 메소드의 선언
abstract 반환타입 메소드이름();

6. final 키워드

  • 클래스, 필드, 메소드를 수정할 수 없고 최종 상태임을 선언하고자 할 때 붙여준다.
  • 클래스, 필드, 메소드에 붙었을 때 각각의 해석이 조금씩 다르다.
    - 'final + 클래스' : 해당 클래스는 최종적인 클래스이므로 더이상 자식 클래스를 만들 수 없고 상속할 수 없다.
    - 'final + 메소드' : 해당 메소드는 최종적인 메소드이므로 오버라이딩 할 수 없다.
    - 'final + 필드(멤버변수)' : 해당 필드는 초기값 설정 후 더이상 값을 변경할 수 없다.

7. object 클래스

  • 자바에서 가장 기본적인 동작을 수행하는 클래스들의 집합인 java.lang 패키지 내에서 가장 많이 사용되는 클래스
  • 모든 자바 클래스의 최고 조상 클래스
  • 자바의 모든 클래스는 object클래스의 모든 메소드를 바로 사용할 수 있다.
  • 필드(멤버변수)를 가지지 않고 11개의 메소드로만 구성되어 있다.

object 클래스 내의 11가지 메소드

profile
진정한 개발자로 가는 길

0개의 댓글