이전 포스팅에서 자바의 객체 배열에 대해서 다뤄봤습니다.
이번 포스팅에서는 객체지향 프로그래밍에서 중요한
자바의 상속에 대해서 다뤄보고자 합니다.
일반적으로 상속이라 하면,,
부모와 자식을 예로 들 수 있죠.
부모로부터 물려받은 유전자, 자산 등등 이런 것들을 물려받으면
자식이 부모로부터 상속받았다고 할 수 있죠.
그러면,,
자바에서 상속은 무엇이냐,
다른 클래스가 가지고 있는 멤버(필드, 메소드)들을
새로 작성할 클래스에서 직접 만들지 않고 상속을 받음으로써
새 클래스가 자신의 멤버처럼 사용할 수 있는 기능을 말합니다.
쉽게 말해,
어떤 클래스에 메소드가 있을 때,
다른 클래스에서 위 메소드를 사용하고자 하면
새로 메소드를 작성하는 것이 아니라 상속받을 수 있다는 말이죠.
왜 이런 상속을 이용하는것이냐,
상속의 목적은
- 클래스의 재사용
- 연관된 일련의 클래스들에 대한 공통적인 규약 정의
이렇게 볼 수 있습니다.
상속의 장점은
- 보다 적은 양의 코드로 새로운 클래스 작성 가능
- 코드를 공통적으로 관리하기 때문에 코드의 추가 및 변경 용이
- 코드의 중복을 제거하여 프로그램의 생산성/유지보수에 크게 기여
상속의 특징으로는
1. 모든 클래스는 Object클래스의 후손
Object클래스가 제공하는 메소드를 오버 라이딩하여 메소드 재구현 가능
ex) java.lang.String 클래스의 equals()와 toString()
2. 부모 클래스의 생성자, 초기화 블록은 상속 안 됨
자식 클래스 생성 시, 부모 클래스 생성자가 먼저 실행됩니다.
자식 클래스 생성자 안에 부모 클래스 생성자를 호출하고 싶으면
super() 활용하면 됩니다.
3. 부모의 private멤버는 상속은 되지만 직접 접근 불가
자식 객체 생성 시에 부모의 필드 값도 전달받은 경우,
자식 생성자 안에서 부모의 private 필드에 직접 접근하여 대입 불가합니다.
따라서 부모의 필드에 접근해 이용을 하고자 하려면,
super() 이용하여 전달받은 부모 필드 값을 부모 생성자 쪽으로 넘겨 생성하거나,
setter, getter 메소드를 이용하여 접근합니다.
상속을 표현하고자 하려면, extends라는 용어를 사용하면 되는데요.
위와 같이 '자식 클래스 extends 부모클래스'
이렇게 사용하면 됩니다.
프로그램 언어에서 상속은
단일 상속, 다중 상속 두 가지가 있는데요.
자바에서는 단일 상속만 지원합니다.
그 이유는 아래 그림을 보면 알 수 있습니다.
C 라는 클래스는 A,B 클래스 둘 다 로부터 상속을 받았다고 합시다.
A클래스에도 a라는 변수가 있고,
B클래스에도 a라는 변수가 있다면,
C클래스에서 a 변수를 상속받을 때, 어느 클래스에 있는 a인지 헷갈리기 때문이죠.
그러면 상속받은 클래스는
부모 클래스에 메소드나 변수의 접근을 할 수 없을까요?
불가능은 없습니다.
super라는 키워드를 이용하면 부모클래스에 접근이 가능하죠.
super란,
부모 생성자를 호출하는 메소드로,
기본적으로 후손 생성자에 부모 생성자가 포함되어 있습니다.
후손 객체 생성 시에는 부모부터 생성이 되기 때문에
후손 클래스 생성자 안에는 부모 생성자를 호출하는 super()가 첫 줄에 존재합니다.
(부모 생성자가 가장 먼저 실행되어야 하기 때문에,
명시적으로 작성 시에도 반드시 첫 줄에만 작성)
매개변수 있는 부모 생성자 호출은 super(매개변수...)를 넣으면 됩니다.
그렇다면 생성자가 아닌 부모 클래스의 메소드나 변수에 접근하고 싶을 때,
super. 키워드를 이용해줍니다.
super. 이란,
상속을 통한 자식 클래스 정의 시,
해당 자식 클래스의 부모 객체를 가리키는 참조 변수로
자식 클래스 내에서 부모 클래스 객체에 접근하여 필드나 메소드 호출 시 사용합니다.
예를 들어,,
부모 클래스에 public int age라는 변수가 있다면
자식 클래스에서 super.age로 접근할 수 있습니다.
여기서 주의할 점은 아무리 상속받았다 하더라도,
부모 클래스 필드의 접근 제한자가 private라면
자식 class에서도 사용할 수 없습니다.
다음으로 알아볼 것은 오버라이딩(Overriding)인데요.
상속 파트에서 제일 중요하다면 중요한 부분입니다.
그만큼 실전에서도 많이 쓰이는데요.
오버라이딩 이란,
자식 클래스가 상속받은 부모 메소드를 재작성하는 것으로,
부모가 제공하는 기능을 후손이 일부 고쳐 사용하겠다는 의미로
자식 객체를 통한 실행 시 후손 것이 우선권을 가집니다.
오버라이딩의 특징으로는
- 메소드 헤드라인 위에 반드시 Annotation 으로 @Override 표시합니다.
- 접근 제어자를 부모 것보다 같거나 넓은 범위로 변경 가능
- 부모 메소드의 예외처리 클래스 처리 범위보다 좁은 범위로 예외처리 클래스 수정 가능
위와 같이 있습니다.
이해가 안 가는 부분은 추후에 따로 다룰 내용에도 포함되어 있어
나중에 다시 다뤄보도록 하겠습니다.
오버라이딩의 성립 조건은 아래와 같습니다.
참고하시길 바랍니다.
여기서 final은 상수 지정이라는 의미가 아니라,
'프로그램 실행 후 한 번만 초기화한다' 는 의미입니다.
오버라이딩을 알아봤더니 전에 다뤄봤던 오버로딩이 생각나는군요..
하지만 둘은 전혀 다른 역할을 합니다.
해당 표를 살펴보면서 다시 한번 익혀봅시다.
마지막으로 다뤄볼 건 final 예약어인데요.
이전 포스팅에서 변하지 않는 상수를 지정해줄 때 쓰였었죠.
클래스에나 메소드에나 final 예약어가 쓰일 때도 맥락은 비슷합니다.
클래스 앞에 쓰일 때와 메소드 앞에 쓰일 때의 차이를
잘 살피시길 바랍니다.
지금까지 자바에서 상속에 대해 알아봤습니다.
그럼 본격적으로 상속의 예제를 풀어봅시다.
자바 상속 예제
난이도 ★★★☆
예제 1
Q : Student 클래스와 Person 클래스를 작성하여라.
그리고 Student의 정보를 Person에서 상속받아 Student의 정보를 출력하라.
(모두 같은 패키지에 작성하라, Student 클래스에서는 정보를 나타내는 변수를 선언하지 않는다.)
● 사람의 정보가 있는 Person 클래스가 있다.
// 해당 클래스에 이름, 나이를 나타내는 필드를 선언하여라.
// 해당 클래스에 이름, 나이를 초기화하는 생성자를 작성하여라.
// 해당 클래스에 이름, 나이 정보를 출력하는 메소드를 작성하여라.
결과
풀이 :
class Person {
protected String name;
protected int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
class Student extends Person {
public Student(String name, int age) {
this.setName(name);
this.setAge(age);
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
public class Sample1 {
public static void main(String[] args) {
Student s = new Student("홍길동", 30);
System.out.println(s);
}
}
난이도 ★★★★
예제 2
Q : 문제 1의 코드를 그대로 사용하여, 아래 요구사항에 따라 Student 클래스를 재작성하고
군인의 정보를 담는 Soldier 클래스와 직원의 정보를 담는 Employee 클래스를 작성하여라.
(모두 같은 패키지에 작성하라,
모든 클래스는 부모 클래스인 Person을 상속받기에 이름과 나이를 입력받는 필드는
상속받아서 사용한다.)
● 학생의 정보가 있는 Student 클래스가 있다.
// 해당 클래스에 학년, 반, 학번, 성적을 나타내는 필드를 선언하여라.
// 해당 클래스에 이름, 나이를 초기화하는 생성자를 작성하여라.
// 해당 클래스에 이름, 나이 정보를 출력하는 메소드를 작성하여라.
● 군인의 정보가 있는 Soldier 클래스가 있다.
// 해당 클래스에 사단, 중대, 소대, 군번, 종과를 나타내는 필드를 선언하여라.
// 해당 클래스에 생성자를 작성하여라.
// 해당 클래스에 필드 정보를 출력하는 메소드를 작성하여라.
● 직원의 정보가 있는 Employee 클래스가 있다.
// 해당 클래스에 회사, 직급, 부서를 나타내는 필드를 선언하여라.
// 해당 클래스에 생성자를 작성하여라.
// 해당 클래스에 필드 정보를 출력하는 메소드를 작성하여라.
결과
풀이 :
package com.kh.exam12;
class Person {
protected String name;
protected int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
class Student extends Person {
private int grade;
private int group;
private int stuNum;
private int record;
public Student(int grade, int group, int stuNum, int record) {
this.grade = grade;
this.group = group;
this.stuNum = stuNum;
this.record = record;
}
public Student(String name, int age) {
this.setName(name);
this.setAge(age);
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
class Employee extends Person {
private String company;
private String rank;
private String dept;
public Employee(String name, int age, String company, String rank, String dept) {
this.name = name;
this.age = age;
this.company = company;
this.rank = rank;
this.dept = dept;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getRank() {
return rank;
}
public void setRank(String rank) {
this.rank = rank;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
@Override
public String toString() {
return "=====직원정보=====\n이름 : " + name +
" \n나이 : " + age +
"세\n회사 : " + company +
" \n직급 : " + rank +
" \n부서 : " + dept +
"\n==============";
}
}
class Soldier extends Person {
private String division;
private String company;
private String platoon;
private int solNum; // 군번
private String species; // 종과
public Soldier(String name, int age, int solNum, String division, String company, String platoon, String species) {
this.name = name;
this.age = age;
this.solNum = solNum;
this.division = division;
this.company = company;
this.platoon = platoon;
this.species = species;
}
public String getDivision() {
return division;
}
public void setDivision(String division) {
this.division = division;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getPlatoon() {
return platoon;
}
public void setPlatoon(String platoon) {
this.platoon = platoon;
}
@Override
public String toString() {
return "=====군인정보=====\n이름 : " + name +
" \n나이 : " + age +
"세\n군번 : " + solNum +
" \n사단 : " + division +
" \n중대 : " + company +
" \n소대 : " + platoon +
" \n종과 : " + species +
"\n==============";
}
}
public class Sample1 {
public static void main(String[] args) {
Student s = new Student("홍길동", 30);
// s.setName("홍길동"); s.setAge(30);
System.out.println(s);
Soldier sd = new Soldier("동길동", 25, 12423232 , "3야수교", "4중대", "2소대", "조교");
System.out.println(sd);
System.out.println();
Employee e = new Employee("카카오", 25, "풀스택 개발","김길동", "전무");
System.out.println(e);
}
}
이상 java의 상속 실습 문제를 마치겠습니다.
다음 포스팅에선 상속 실습문제를 풀어보고자 합니다.
https://healthdevelop.tistory.com/entry/java15
'Java > Java' 카테고리의 다른 글
[Java] 자바 다형성 | 자바 인터페이스 | java 추상클래스 | instanceof (java로 웹개발하기)(day16) (0) | 2021.08.18 |
---|---|
[Java] 자바 상속 | 자바 상속 예제 | java 상속 실습문제 | Override (java로 웹개발하기)(day15) (0) | 2021.08.13 |
[Java] 자바 객체 배열 (java로 웹개발하기)(day13) (0) | 2021.08.11 |
[Java] 자바 객체 생성 예제 | 자바 메소드 예제 | java 객체 예제 | 실습문제 (java로 웹개발하기)(day12) (0) | 2021.08.10 |
[Java] 자바 메소드 예제 | java 객체 예제 | 실습문제 (java로 웹개발하기)(day11) (0) | 2021.08.06 |