[윤성우의 열혈 Java 프로그래밍] Chapter 16 - 클래스의 상속 3: 상속의 목적
카테고리: Java lang
태그: java
16-1. 상속이 도움이 되는 상황의 소개
상속을 하는 이유: 연관된 일련의 클래스들에 대해 공통적인 규약을 정의할 수 있다.
- 단순한 인맥 관리 프로그램
다음과 같은 두 부류의 인맥을 관리하는 프로그램이 있다고 가정하자.
1) 대학 동창: 이름, 전공, 전화번호
2) 직장 동료: 이름, 부서, 전화번호
class UniFriend extends Friend{ // 대학 동창
private String name;
private String major; // 전공
private String phone;
public UniFriend(String name, String major, String phone) {
this.name = name;
this.major = major;
this.phone = phone;
}
public void showInfo() {
System.out.println("이름: " + name);
System.out.println("전공: " + major);
System.out.println("전화: " + phone);
}
}
class CompFriend extends Friend{ // 직장 동료
private String name;
private String department; // 부서
private String phone;
public CompFriend(String name, String department, String phone) {
this.name = name;
this.department = department;
this.phone = phone;
}
public void showInfo() {
System.out.println("이름: " + name);
System.out.println("부서: " + department);
System.out.println("전화: " + phone);
}
}
public class MyFriends {
public static void main(String[] args) {
UnivFriend[] ufrns = new UnivFriend[2]; // 대학 친구
CompFriend[] cfrns = new CompFriend[2]; // 직장 친구
ufrns[0] = new UniFriend("LEE", "Computer", "010-999-9999");
ufrns[1] = new UniFriend("KIM", "Social", "010-888-8888");
cfrns[0] = new CompFriend("LEE", "Dev", "010-777-7777");
cfrns[1] = new CompFriend("KIM", "Market", "010-666-6666");
for (UnivFriend u: ufrns) {
ufrns.showInfo();
}
for (UnivFriend u: ufrns) {
cfrns.showInfo();
}
}
}
코드를 잘 관찰해보면 다음을 알 수 있다.
- 인스턴스를 저장하는 배열이 두 개이다.
- 친구의 부류에 따라 정보를 저장하는 과정이 나뉜다. -> 저장에 필요한 배열과 변수가 다르기 때문
- 저장된 정보를 출력할 때 두 개의 for문을 작성해야 한다. -> 출력에 사용되는 배열과 변수가 다르기 때문
이렇게 배열이 두 개이므로 무엇을 하건 그 과정이 둘로 나뉜다.
대상마다 배열이 필요하게 되면 늘어나는 배열의 수만큼 프로그램은 더 복잡해진다.
- 인맥 관리 프로그램의 문제를 상속으로 해결하자.
그렇다면, UnivFriend 클래스와 CompFriend 클래스에 공통적인 규약을 적용하여 코드를 개선해보자!
class Friend {
protected String name;
protected String phone;
public Friend(String name, String phone) {
this.name = name;
this.phone = phone;
}
public void showInfo() {
System.out.println("이름: " + name);
System.out.println("전화: " + phone);
}
}
class UniFriend extends Friend{
private String major;
public UniFriend(String name, String major, String phone) {
super(name, phone);
this.major = major;
}
public void showInfo() {
super.showInfo();
System.out.println("전공: " + major);
}
}
class CompFriend extends Friend{
private String department;
public CompFriend(String name, String department, String phone) {
super(name, phone);
this.department = department;
}
public void showInfo() {
super.showInfo();
System.out.println("부서: " + department);
}
}
public class MyFriends {
public static void main(String[] args) {
Friend[] friends = new Friend[4];
friends[0] = new UniFriend("LEE", "Computer", "010-999-9999");
friends[1] = new UniFriend("KIM", "Social", "010-888-8888");
friends[2] = new CompFriend("LEE", "Dev", "010-777-7777");
friends[3] = new CompFriend("KIM", "Market", "010-666-6666");
for (Friend f: friends) {
f.showInfo();
System.out.println();
}
}
}
Friend 클래스를 만듦으로써 다음과 같은 효과를 얻었다.
- 인스턴스를 저장하는 배열이 하나이다.
- 정보를 저장하는 과정이 나뉘지 않는다.
- 저장된 정보를 모두 출력할 때 하나의 for문으로 충분하다.
Friend 클래스는 코드의 재활용 같은 목적으로 추가한 클래스가 아니다.
UnivFriend 클래스와 CompFriend 클래스에 공통 규약을 적용하기 위해 정의된 클래스이다.
16-2. Object 클래스와 final 선언 그리고 @Override
- 모든 클래스는 Object 클래스를 상속한다.
자바의 모든 클래스는 직접 혹은 간접적으로 java.lang 패키지에 묶여 있는 Object 클래스를 상속하게 된다.
이는 자바의 모든 인스턴스에 공통된 기준 및 규약을 적용하기 위함이다.
- 클래스와 메소드의 final 선언
클래스를 정의할 때 해당 클래스를 다른 클래스가 상속하는 것을 원치 않는다면, 앞에 final 선언을 붙여주면 된다.
public final class MyLastCLS {...}
메소드의 정의에 final 선언을 추가하여 해당 메소드의 오버라이딩을 허용하지 않을 수도 있다.
class Simple {
public final void func(int n){...}
}
- @Override
개발자의 실수로 인한 오류는 컴파일단계에서 발견되는 것이 가장 좋다.
하지만 다음의 예시처럼 컴파일 시 오류가 발생하지 않는 상황도 존재한다.
class ParentAdder {
public int add(int a, int b) {
return a + b;
}
}
class ChildAdder extends ParentAdder {
// 상위 클래스의 add를 오버라이딩 하려는 의도 -> 오버로딩이 되어버렸다..
public double add(double a, double b) {
return a + b;
}
}
public class OverrideMistake {
public static void main(String[] args) {
ParentAdder adder = new ChildAdder();
System.out.println(adder.add(3, 4));
}
}
어노테이션은 ‘자바 컴파일러에게 메시지를 전달하는 목적의 메모’이다.
다음과 같이 어노테이션을 달아주면 된다.
class ChildAdder extends ParentAdder {
@Override
public double add(double a, double b) {
return a + b;
}
}
이렇게 달아놓으면 컴파일러는 오버라이딩이 제대로 되었는지 확인을 하고, 개발자의 의도대로 되지 않았다면 컴파일 단계에서 검증해준다.
댓글 남기기