JAVA_08_상속

송지윤·2024년 2월 15일

Java

목록 보기
14/22
post-thumbnail

상속(Inheritance)

부모로부터 자식이 물려받음
부모객체, 자식객체

부모 객체
부모가 가진(속성 + 기능)

자식 객체 (부모에게 상속 받음)
자식(자기만의 속성 + 기능) + 부모가 가진(속성 + 기능)

상속

다른 클래스(부모)가 가지고 있는 멤버(필드(속성), 메소드(기능))들을 새로 작성할 클래스(자식)에서 직접 만들지 않고 상속을 받음으로써 새 클래스가 자신의 멤버처럼 사용할 수 있는 기능

상속의 목적

클래스의 재사용, 연관된 일련의 클래스들에 대한 공통적인 규약 정의

상속의 장점

  1. 보다 적은 양의 코드로 새로운 클래스 작성 가능(코드 길이 감소)
  2. 코드를 공통적으로 관리하기 때문에 코드의 추가 및 변경 용이
  3. 코드의 중복을 제거하여 프로그램의 생산성과 유지보수에 크게 기여

방법

클래스 간의 상속 시에는 extends 키워드 사용

표현식

[접근제한자] class 클래스명 extends 클래스명 {}

public class Academy(자식) extends Company(부모) {}

Object 클래스

  • 모든 클래스의 최상위 부모
  • class 선언부에 상속 구문이 하나도 작성되어있지 않다면
    컴파일러가 extends Object 구문을 추가해줌

DTO(Data Transfer Object) : 비지니스 계층과 데이터 교환을 위해 사용하는 객체.
데이터 값 교환 객체

사용 연습

Person 클래스 (부모 객체)

package ehu.kh.inheritance.model.dto;

public class Person /*extends Object*/{
	
	private String name; // 이름
	private int age; // 나이
	private String nationality; // 국적
	
	public Person() {}
	
	public Person(String name, int age, String nationality) {

		super();
		
		this.name = name;
		this.age = age;
		this.nationality = nationality;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getNationality() {
		return nationality;
	}

	public void setNationality(String nationality) {
		this.nationality = nationality;
	}
	
	public void breath() {
		System.out.println("사람은 코나 입으로 숨을 쉰다.");
	}
	
	public void move() {
		System.out.println("사람은 움직일 수 있다.");
	}
	
}

Student 클래스 (자식 객체)

Object
	ㄴ Person
		ㄴ Student

student 클래스에 Person 클래스 내용을 연장한다.
== Student 클래스에 Person 클래스 내용(필드, 메서드)을 추가하여 확장한다.

상속
자식 extends 부모

package ehu.kh.inheritance.model.dto;

public class Student extends Person {

	private int grade; // 학년
	private int classRoom; // 반
	
	public Student() {}

	public Student(String name, int age, String nationality, int grade, int classRoom) {
		
		this.grade = grade;
		this.classRoom = classRoom;
	}

	public int getGrade() {
		return grade;
	}

	public void setGrade(int grade) {
		this.grade = grade;
	}

	public int getClassRoom() {
		return classRoom;
	}

	public void setClassRoom(int classRoom) {
		this.classRoom = classRoom;
	}
	
	
}

InheritanceService 클래스
상속 확인 예제

package ehu.kh.inheritance.model.service;

import ehu.kh.inheritance.model.dto.Person;
import ehu.kh.inheritance.model.dto.Student;

// 비지니스 로직 처리하는 클래스
public class InheritanceService {
	
	public void ex1() {
		
		Person p = new Person();
		
		p.setName("홍길동");
		p.setAge(25);
		p.setNationality("대한민국");
		
		System.out.println(p.getName());
		System.out.println(p.getAge());
		System.out.println(p.getNationality());
	
		System.out.println("=========================================");
		
		// Student 객체 생성
		Student std = new Student();
		
		// Student만의 고유한 필드
		std.setGrade(3);
		std.setClassRoom(5);
		
		// Person 클래스로부터 상속받은 필드, 메서드
		std.setName("고길동");
		std.setAge(19);
		std.setNationality("대한민국");
		
		System.out.println(std.getGrade());
		System.out.println(std.getClassRoom());
		System.out.println(std.getName());
		System.out.println(std.getAge());
		System.out.println(std.getNationality());
	}
}

출력 결과

홍길동
25
대한민국
=========================================
3
5
고길동
19
대한민국

단일 상속과 다중 상속

단일 상속(Single Inheritance)

클래스간의 관계가 다중 상속보다 명확하고 신뢰성 있는 코드 작성
자바에서는 다중 상속 미지원 -> 단일상속만 지원

다중 상속(Multiple Inheritance)

C++에서 가능한 기능으로 여러 클래스로부터 상속을 받으며 복합적인 기능을 가진 클래스를 쉽게 작성 가능
서로 다른 클래스로부터 상속 받은 멤버 간의 이름이 같은 경우 문제 발생

상속의 특징

1. 모든 클래스는 Object 클래스의 후손

Object클래스가 제공하는 메소드를 오버라이딩하여 메소드 재구현 가능
ex) java.lang.String 클래스의 equals()와 toString()

2. 부모클래스의 생성자, 초기화 블록은 상속 안됨

자식 클래스 생성 시, 부모 클래스 생성자가 먼저 실행
자식 클래스 생성자 안에서 부모 클래스 생성자 호출을 명시하고 싶으면 super() 활용

3. 부모의 private멤버는 상속은 되지만 직접 접근 불가

자식 객체 생성 시에 부모의 필드 값도 전달 받은 경우, 자식 생성자 안에서 부모의 private 필드에 직접 접근하여 대입 불가
super() 이용하여 전달받은 부모 필드 값을 부모 생성자 쪽으로 넘겨서 생성하거나 setter, getter 메소드를 이용하여 접근

super()와 super.

super()

부모 객체의 생성자를 호출하는 메소드로 기본적으로 후손 생성자에 부모 생성자 포함
후손 객체 생성 시에는 부모부터 생성이 되기 때문에 후손 클래스 생성자 안에는 부모 생성자를 호출하는 super()가 첫 줄에 존재 (부모 생성자가 가장 먼저 실행되어야 하기 때문에 명시적으로 작성 시에도 반드시 첫 줄에만 작성)
매개변수 있는 부모 생성자 호출은 super(매개변수, 매개변수)를 넣으면 됨

사용 연습

Student 클래스

부모의 setter 를 이용할 수 있지만 비효율적임.
setName(name);
setAge(age);
setNationality(nationality);

super();
부모의 매개변수 생성자에게 전달
ctrl + 클릭 : Person 의 매개변수 생성자로 이동됨

	public Student(String name, int age, String nationality, int grade, int classRoom) {
		
		super(name, age, nationality);
		
		this.grade = grade;
		this.classRoom = classRoom;
	}

InheritanceService 클래스

super() 생성자 이용방법

	public void ex2() {
		
		// Student 매개변수 5개짜리 생성자
		Student std = new Student("김철수", 17, "한국", 1, 3);
		
		System.out.println(std.getName());
		System.out.println(std.getAge());
		System.out.println(std.getNationality());
		System.out.println(std.getGrade());
		System.out.println(std.getClassRoom());
		
	}

출력 결과

김철수
17
한국
1
3

super.

상속을 통한 자식 클래스 정의 시 해당 자식 클래스의 부모 객체를 가리키는 참조변수
자식 클래스 내에서 부모 클래스 객체에 접근하여 필드나 메소드 호출 시 사용

사용 연습

Person 클래스

	// alt shift s Generate toString 클릭
	
	@Override
	public String toString() {
		// Object의 toString() 재정의
		
		return name + " / " + age + " / " + nationality;
	}

Employee 클래스

	@Override
	public String toString() {
		return super.toString() + " / " + company;
	}

오버라이딩(Overriding)

오버로딩(overloading)과의 차이점 명확하게 구분해야함

자식 클래스가 상속 받은 부모 메소드를 재작성(재정의) 하는 것
부모가 제공하는 기능을 후손이 일부 고쳐 사용하겠다는 의미로
자식 객체를 통한 실행 시 후손 것이 우선권을 가짐(덮어쓰기 된 게 먼저 나온다.)

특징

@Override
public void ex1() {}

메소드 헤드라인 위에 반드시 Annotation, @Override 표시
접근 제어자를 부모 것보다 같거나 넓은 범위로 변경 가능
부모 메소드의 예외처리 클래스 처리범위보다 좁은 범위로 예외처리 클래스 수정 가능

성립 조건

부모 클래스의 메소드와 자식 클래스의 메소드 비교

  • 메소드 이름 동일
  • 매개변수의 개수, 타입, 순서 동일
    (Overloading과 완전 반대)
  • 리턴 타입 동일
  • private 메소드 오버라이딩 불가

사용 연습 1

Employee 클래스

Person 으로부터 상속받은 메서드 중
move() 메서드를 Employee 에 맞게 재정의 (==오버라이딩)

@Override 어노테이션 : 해당 메서드가 오버라이딩 되었음을 컴파일러에게 알려주는 역할
-> 컴파일러에게 문법체크 등 하도록 알린다.

어노테이션(Annotation) : 컴파일러에게 알려주기 위한 코드 (컴파일러 인식용 주석)

	@Override
	public void move() {
		
		System.out.println("오버라이딩된 move()");
		System.out.println("효율적으로 빨리 일하고 움직인다.");
	}

InheritanceService 클래스

	public void ex3() {
		
		Student std = new Student();
		Employee emp = new Employee();
		
        // 오버라이딩 X -> Person 의 메소드
		std.move();
        
        // 오버라이딩 O -> Employee 의 메소드
		emp.move();
	}

출력 결과

사람은 움직일 수 있다.
오버라이딩된 move()
효율적으로 빨리 일하고 움직인다.

final 예약어

final 클래스

상속이 불가능한 클래스

public final class finalClass {}

final 클래스 -> 상속 불가
The type GrandChild1 cannot subclass the final class Employee
상속 받은 곳에서 에러 뜸

  • 제공되는 클래스 그대로 사용해야 하는 경우
    String

final 메소드

상속 시 오버라이딩이 불가능한 메소드
메서드의 기능이 변하면 안되는 경우
오버라이딩 하려고 하면
Cannot override the final method from Employee
에러뜸

public final void method() {}

0개의 댓글