안녕하세요, 여행벌입니다.

오늘은 객체지향 언어인 자바의 중요한 문법, 상속에 대해서 포스팅해보겠습니다.


상속(Inheritance) 의 객체지향적 역할

"상속이란 연관된 일련의 클래스들에 대해 공통적인 규약을 정의해준다."

 

 상속이란 문법의 가장 큰 역할은 위와 같습니다. 그럼 어떻게 상속을 사용하고, 상속의 특징으로는 어떤 특징들이 있는지 알아보겠습니다.

상속(Inheritance) 이란

 상속은 쉽게 얘기하면 이미 기존에 정의된 클래스에 메소드와 변수를 추가하여 새로운 클래스를 정의하는 것을 의미합니다. 즉, 이미 만들어진 클래스에 우리가 원하는 기능과 데이터를 추가해서 새로운 클래스를 만드는 행위입니다.

 extends 키워드를 이용해 상속을 활용할 수 있습니다.

 

 그럼, 간단하게 이름을 가지고 있는 사람이라는 클래스에 핸드폰 번호도 추가해서 새롭게 클래스를 만들어보겠습니다.

class people{
	String name;
    void tellYourName(){}
}

class richPeople extends people{
	String phoneNum;
    void tellYourPhontNum(){}
}

 people이라는 클래스를 extends 상속해서 richPeople이라는 새로운 클래스를 만들었습니다.

그럼, richPeople 이라는 새로운 클래스는 people 클래스에 있는 변수와 메소드를 가져와 사용할 수 있습니다. 즉, richPeople이라는 클래스는 실제로 아래 그림과 같습니다.

이처럼

● 상속을 하는 클래스를 하위 클래스, 자식 클래스

상속을 당하는 클래스를 상위 클래스, 부모클래스  라고 부릅니다.  

상속(Inheritance) 과 생성자

 모든 클래스는 생성자 메소드가 존재한다고 앞의 포스팅에서 얘기했습니다. 그러면, 상속 관계에서는 생성자 호출이 어떤 식으로 진행될까요??

 다음 예제를 통해서 하위 클래스 인스턴스를 생성하면 생성자 호출이 어떻게 진행되는지 보겠습니다.

package Hello;

class people{
	String name;
	public people() {
		System.out.println("상위클래스생성사호출");
	}
}

class richPeople extends people{
	String phoneNum;
	public richPeople() {
		System.out.println("하위클래스생성자호출");
	}
}

public class test{
	public static void main(String args[]) {
		new richPeople();
	}
}
[Output]
상위클래스생성사호출
하위클래스생성자호출

 예시를 통해 아래와 같은 두 가지 사실을 알 수 있습니다.

 

● 하위 클래스의 인스턴스 생성 시 상위 클래스, 하위 클래스의 생성자가 모두 호출된다.

● 하위 클래스의 인스턴스 생성 시 상위 클래스의 생성자가 먼저 호출된다.

 

 즉, 하위 클래스의 인스턴스를 생성할 때 상위 클래스의 생성자를 먼저 호출해줘야 한다는 것을 알 수 있습니다. 따라서, 다음과 같이 클래스의 생성자를 구현할 수 있습니다.

package Hello;

class people{
	String name;
	public people(String name) {
		this.name = name;
	}
}

class richPeople extends people{
	String phoneNum;
	public richPeople(String name, String phoneNum) {
		super(name);
		this.phoneNum = phoneNum;
	}
}

public class test{
	public static void main(String args[]) {
		new richPeople();
	}
}

키워드 super 를 이용하면 '상위 클래스의 생성자 호출' 을 할 수 있습니다.

클래스 변수, 클래스 메소드의 상속

 static 선언이 붙는 클래스 변수와 클래스 메소드는 인스턴스 생성과 상관 없이 유일하게 존재한다고 앞에서 배웠습니다. 따라서, 클래스 변수와 클래스 메소드는 상속의 대상이 아닙니다. 그러면, 상위클래스의 클래스 변수와 클래스 메소드는 하위 클래스에서 이용할 수 있을까요?? 

 접근 수준 지시자가 접근을 허용하면 하위 클래스에서도 상위 클래스의 클래스 변수와 클래스 메소드에 접근이 가능합니다.

package Hello;

class people{
	// 클래스 변수와 메소드
	static int num = 9999;
	static void showNum() {
		System.out.println(num);
	}
	
	String name;
	public people(String name) {
		this.name = name;
	}
}

class richPeople extends people{
	String phoneNum;
	public richPeople(String name, String phoneNum) {
		super(name);
		this.phoneNum = phoneNum;
	}
}

public class test{
	public static void main(String args[]) {
		richPeople ex1 = new richPeople("travlebeee", "010-0000-0000");
		ex1.showNum();
		ex1.num++;
		ex1.showNum();
	}
}
[Output]
9999
10000

 private 접근 수준 지시자로 선언이 되어있다면, 하위 클래스에서 접근할 수 없지만 다른 접근 수준 지시자들은 접근이 가능합니다.

상속과 참조변수

 하위 클래스는 상위 클래스의 특징을 다 가지고 있다고 했습니다. 그러면, 하위 클래스의 참조 변수로 상위 클래스를 참조하거나 상위 클래스의 참조 변수로 하위 클래스를 참조하는 게 가능할까요??

 예시를 통해서 자세히 알아보겠습니다.

class people{
	String name;
	public people(String name) {
		this.name = name;
	}
	
	void showYourName() {
		System.out.println("내이름은 : " + name);
	}
}

class richPeople extends people{
	String phoneNum;
	public richPeople(String name, String phoneNum) {
		super(name);
		this.phoneNum = phoneNum;
	}
	void showYourPhone() {
		System.out.println("내 번호는 : " + phoneNum);
	}
}

 위와 마찬가지로 people 클래스를 richPeople이 상속하고 있는 경우입니다.

 먼저, 상위 클래스의 참조 변수로 하위 클래스를 참조해보겠습니다.

public class test{
	public static void main(String args[]) {
		// 상위 클래스 참조 변수로 하위 클래스 참조
		people p1 = new richPeople("travelbeeee", "010-0000-0000");
		p1.showYourName(); // 가능
		p1.showYourPhone(); // 불가능
	}
}

 richPeople은 people 클래스의 자식이기 때문에, 상위 클래스의 참조 변수로도 하위 클래스의 인스턴스를 참조할 수 있습니다. 하지만, 자바는 참조 변수를 기준으로 판단하기 때문에, people 클래스의 참조 변수 p1은 people 클래스의 메소드인 showYourName() 메소드는 호출이 가능하나 showYourPhone() 메소드는 호출이 불가능합니다.

 

 반대 상황도 보겠습니다.

public class test{
	public static void main(String args[]) {
		// 하위 클래스 참조 변수로 상위 클래스 참조
		richPeople p1 = new people("travelbeeee"); // 불가능
	}
}

 이번에는 하위 클래스 참조 변수로 상위 클래스를 참조하고 있기 때문에, 애초에 참조가 불가능합니다.

 

 상위 클래스가 부모이므로 부모가 자식을 참조할 수는 있으나 하위 클래스인 자식이 부모를 참조할 수는 없다! 라고 외우시면 편할 것 같습니다.


이상으로, 상속에 대한 기본 정리를 마무리해보겠습니다.

다음 포스팅에서는 메소드 오버라이딩을 추가로 정리해보도록 하겠습니다.

+ Recent posts