본문 바로가기
국비 교육/백엔드(Java, Spring)

[자바] 상속(Inheritance), 오버라이딩(Overriding), 추상화 클래스 (Abstract Class)

by 육츠 2024. 1. 25.
Contents 접기

상속

특징

클래스가 다른 클래스의 속성과 행동방식을 물려받아 구현하는 것
상속을 받아 새로 만들어지는 클래스는 자식 클래스(sub class)가 되고 멤버들을 상속해주는 클래스를 부모 클래스(super class)라고한다. (Super Class- Sub Class, Parent Class - Child Class, Base Class-Derived Class)
객체지향 프로그래밍에서 코드의 재사용성과 확장성을 높임으로써 프로그램의 유지보수를 좀 더 쉽게 해준다.

사용 방법

상속을 하기 위해서는 extends 키워드를 사용
상속을 받은 자식 클래스는 부모 클래스에 선언되어 있는 private 접근 제한 을 갖는 필드와 메소드를 제외한 public, protected, default로 선언되어 있는 모든 변수와 메서드를 물려받아 사용할 수 있다.
부모클래스가 먼저 생성된 후 자식 클래스가 생성된다.
final 키워드를 가진 클래스는 상속할 수 없다.

 

관계

Is-a 관계 Has-a 관계
extends로 상속 받은 경우 is-a 관계가 형성되었다고 한다.
예 ) public class Child extends Parent 
다른 클래스를 가지고 있는 경우 has-a 관계가 형성되었다.
예) FitnessUI 에서 FitnessService 클래스를  가지고 있는 모습
      FitnessService service = new FitnessService();

 

형태

public class Child extends Parent {
	...
}

 

SUPER, SUPER()

super super()
- super는 부모 클래스의 멤버를 가리키는 참조변수.

- super를 이용해 부모 클래스의 private를 제외한 멤버변수나 메소드에 접근할 수 있다.
- 부모 객체의 생성자 부모 클래스의 생성자를 호출하는 키워드이다.

- super()는 자식 생성자 내 최상단에 위치해야 하며 다른 문장보다 뒤에 있으면 오류이다

- 자바는 자식 클래스가 생성되기 전에 부모 클래스부터 생성을 해야 하므로 개발자가 명시적으로 super()를 사용하지 않아도 자식 클래스의
생성자 내에 super()가 자동으로 삽입된다.

 

상속 예제

Parent

class Parent{
	private int money = 2000;
	
	//  기본 생성자
	public Parent() {
		super();
		System.out.println("Parent: 기본 생성자");
	}
	
	// 외부에서 값을 받아 대입하는
	public Parent(int money) {
		super();
		this.money = money;
		System.out.println("Parent: 오버로딩 생성자");
	}
	
	public int earning() {
		return this.money * 2;
	}
	
	public void output() {
		System.out.println("부모 현재 자산: " + money + ", 투자 수익: " + this.earning());
	}
	
}

 

Child

class Child extends Parent {
	// 메소드 중 public 인 애들이 상속됨
	private int property = 1000;

	public Child() {
		// super(); 
		System.out.println("Child: 기본 생성자");
		super.earning(); // = this.earnning(); 
		}

	public int gather() {
		return property *= 3; 
	}
	
	public void print() {
		System.out.println("자식 현재 자산: " + property + ", 투자 수익: " + this.gather());
	}
	
}
코드 의미
super();    부모의 기본생성자를 호출    // 안 써도 JVM이 넣는다.

 

main

public class InheritanceTest01 {

	public static void main(String[] args) {
		//Parent p = new Parent();
		//p.output();
		
		Child c = new Child();
		
		 '//Parent: 기본 생성자
		 //Child: 기본 생성자
		c.output();
		c.earning();
		c.gather();
		c.print();
	}
코드 출력
Parent p = new Parent();
p.output();
Parent: 기본 생성자
부모 현재 자산: 2000, 투자 수익: 4000
Child c = new Child();
c.output();
Parent: 기본 생성자
Child: 기본 생성자
부모 현재 자산: 2000, 투자 수익: 4000
c.print(); 자식 현재 자산: 3000, 투자 수익: 9000

 

오버 라이딩 Overriding

- 상속관계에 있는 클래스에서 이미 정의된 메소드를 지식 클래스에서 같은 시그니처를 갖는 메소드로 다시 정의하는 것
- 오버라이딩은 다형성을 지원하는 중요한 기능

같은 예제에서 Parent는 "Parent: 기본생성자 호출" 하는 출력문만 지웠다.

class Child extends Parent {
	// 메소드 중 public 인 애들이 상속됨
	private int property = 1000;

	public Child() {
		// super();       // 안 써도 JVM이 넣는다.
		// 부모의 기본생성자를 호출
		System.out.println("Child: 기본 생성자");
		super.earning(); // = this.earnning(); 
		}
	

	public Child(int property) {
		super();
		this.property = property;
	}


	public int gather() {
		return property *= 3; 
	}
	
	@Override  // 메소드가 상속받은 걸 재정의 했다는 주석
	public void output() {
	// public void output(int a) { // 오버로드
		super.output();
		System.out.println("자식 현재 자산: " + property + ", 투자 수익: " + this.gather());
	}
	
	// 멤버를 스트링으로 만들어서 반환하는
	// 문자열을 무조건 반환하는 메소드
	@Override
	public String toString() {
		return "Child [property=" + property + "]";
	}
	
}
코드 의미
@Override  메소드가 상속받은 걸 재정의 했다는 주석
public void output() { 
    super.output();
    System.out.println("자식 현재 자산: " + property + ", 투자 수익: " + this.gather());
}
부모 클래스의 메서드를 오버라이딩 한 후 parent 의 output 쓰고 싶으면 이렇게 사용하면 된다.
@Override
public String toString() {
    return "Child [property=" + property + "]";
}
최상위에 존재하는 Object 에 존재하는 toString을 오버라이딩 한 것이다.

 

오버로딩과 오버라이딩의 차이점

오버로딩 오버라이딩
public void output(int a){ .. @Override 
public void output() {..
오버로딩은 매개변수가 달라진다. 오버라이딩은 매개변수까지 형태가 아예 똑같다.

 

추상클래스 Abstract Class

= 객체는 생성하지 않는 상속 전용 클래스

- 하나 이상의 추상메소드를 포함하거나 class 선언부에 abstract 키워드를 갖고있는 클래스.
- 추상 메소드는 선언만 되어 있고 구현이 없는 메소드를 말한다.
- 추상 클래스는 일반 클래스와 달리 단독으로 객체를 생성할 수 없으며,
반드시 추상 클래스를 실제 클래스 통해서만 객체를 생성할 수 있다. 

- 일반 클래스와 동일하게 멤버변수, 생성자, 일반 메소드, 추상메소드(메소드의 본체가 없는 메소드) 가 존재한다.
- 추상클래스를 상속받은 자식클래스도 추상클래스가 된다.
   때문에 추상 메소드를 오버라이드 하면 일반 클래스가 되어 객체 생성을 할 수 있다.
- 만약 추상 메소드를 가지고 있지 않다면 바로 일반클래스가 되기 때문에 오버라이드를 할 필요는 없다.

 

용도

공통의 기능을 정의하여 자식클래스에서 상속받아 사용하기 위해 , 다형성을 구현하기 위해

package ticket.vo;

//public class Ticket { (원래)
public abstract class Ticket {  //(추상화)

....
	//추상메소드
	public abstract void myMethod();
	// 이제 상속받은 애들도 추상클래스가 됨
}


package ticket.main;

import ticket.vo.AdvanceTicket;
import ticket.vo.WalkupTicket;

public class TicketMain {
	public static void main(String[] args) {
    
    ..
    
    Ticket t = new Ticket();
    }
}
코드 의미
public class Ticket {  객체 생성 가능
public abstract class Ticket {  객체 생성 가능
public abstract class Ticket { 
    public abstract void myMethod();
객체 생성 불가능.
하지만 사용시에 추상 메소드를 오버라이드 하면 일반 클래스가 되어 객체 생성을 할 수 있다.

 

abstract -> interface 


상속에서 잠깐 나왔던 '클래스 다이어 그램'을 이해하는데 도움이 되었던 티스토리!
https://brownbears.tistory.com/577

 

[UML] 클래스 다이어그램 (Class Diagram)

클래스 다이어그램은 구조 다이어그램으로 클래스 내부 구성요소 및 클래스 간의 관계를 도식화하여 시스템의 특정 모듈이나 일부 및 전체를 구조화 합니다. 개발 하기 전, 클래스 다이어그램

brownbears.tistory.com