본문 바로가기
프로그래밍 공부/Java

[lesson] Java 프로그래밍 언어 - 상속

by Luna_lua 2021. 7. 28.
반응형

클래스를 배웠으니 그다음 단계인 상속을 배워보려 합니다.

상속의 사전적 단어를 한번 확인해 보면 '다른 사람에게 권리와 의무의 일체를 이어 주거나, 다른 사람이  그 권리와 의무의 일체를 이어받는 일.'이라고 나와있습니다. 이와 동일한 내용으로 하나의 클래스가 다른 하나에 그 권리와 의무 즉 선언된 필드들을 사용할 수 있도록 전달해준다는 의미로 보면 됩니다.

 

<상속 문법>

class A{
	A필드
}

class B extends A{
	A, B필드
}

상속을 받는 문법은 extends라는 키워드로 B extends A로 사용하며 A의 필드를 B가 사용할 수 있게 됩니다.

 

A는 부모클래스, 상위클래스, 슈퍼클래스, 기반클래스 라고 부르며,

B는 자식클래스, 하위클래스, 서브클래스, 파생클래스 라고 부릅니다.

저는 이중에서 주로 사용하고 개발자들이 주로 부르는 내용으로 부모/자식 클래스라고 부르겠습니다.

 

클래스의 객체 생성시 생성자가 호출되고 그것으로 객체가 생성된다고 했습니다. 그렇다면 부모, 자식간에 객체 생성은 어떻게 할까요? 거기다 자식이 부모의 필드를 사용할 수 있다고 했는데 아직 추상적인 클래스만 가지고 필드를 어떻게 사용하고 있는걸까요?

 

바로 상속을 받은 자식의 생성자 호출시 부모의 생성자를 같이 호출합니다. 바로 super();라고 부르는 생성자입니다.

 

super()부모 생성자라 부르며, 자식 클래스 타입의 객체로 부모 필드에 접근할 수 있습니다.
하지만 자식 생성자만 호출하기 때문에, 자식 필드만 메모리에 할당된다고 생각할 수 도 있습니다. 

사실 자식 생성자에는 항상 부모 생성자를 호출하며, 자식 생성자 호출 시 부모와 자식 필드 모두 메모리에 할당됩니다.
이 때 부모 생성자를 호출하는 방법은 super()를 사용합니다.
그러나 클래스의 기본생성자와 같이 super()를 작성하지 않아도 컴파일러가 자동으로 작성해주므로 너무 신경쓰지 않아도 됩니다. 

 

<예시>

class Monkey{
	String name;	
	int age;
   
	public Monkey() {
		System.out.println("부모 생성자 호출됨");
	}
}

class Human extends Monkey{
	int money;
	String position;
   
	public Human() {
		super();
		System.out.println("자식 생성자 호출");
	}
}

★Point! super();는 자식 클래스에 관한 객체는 자식이 있기 전에 부모가 있어야 상속을 받아 자식의 객체를 만들수 있기때문에 자식의 생성자에서 맨 처음에 사용해주어야 합니다!

 

그럼 이런 생각이 들지 않나요? 부모의 필드를 가져온다고 했으니까... 메소드도 쓸 수 있는건데 아... 이 메소드가 이런작동하면 좋을텐데 이런 생각 말입니다. 즉, 부모의 메소드 중에 내용을 자식에 맞게 재정의 할 수 없을까?

 

여기서 나오는것이 바로 다형성의 2번째 내용인 오버라이딩(재정의)입니다.

오버라이딩이란 부모 필드에서 선언한 메소드를 자식 필드에서 수정하고자 할 때 재정의를 해야합니다.
이는 자식에서 부모 필드의 메소드와 동일한 이름으로 선언하는 것입니다.
부모 필드가 메모리에 먼저 할당되고 a라는 메소드가 먼저 올라간다고 하면, 자식 필드가 메모리에 할당되면서 재정의한 a 메소드가 새롭게 만들어지는 것이 아닌 기존에 할당된 a 메소드 저장공간에 새롭게 재정의한 소스코드의 주소가 들어가게 됩니다. 따라서 자식 객체로 a 메소드에 접근하면 자식 필드에서 재정의한 소스코드의 내용이 읽히게 됩니다.

 

class Monkey{
	String name;	
	int age;
   
	public Monkey() {
		System.out.println("부모 생성자 호출됨");
	}
    
	void walk() {
		System.out.println("두발 또는 네발로 걷는다.");
	}
}

class Human extends Monkey{
	int money;
	String position;
   
	public Human() {
		super();
		System.out.println("자식 생성자 호출");
	}
    
	@Override
	void walk() {
		System.out.println("두 발로 걷습니다.");
	}
}

 

위의 내용을 보면 @Override라고 써져있는것이 있습니다. 이것은 그냥 오버라이드 했습니다! 라는 글이 아닌

어노테이션이라고 해서 이 문구를 보면 컴파일러가 번역할때 부모의 메소드의 메모리에 찾아가 덮어씌웁니다.
이것 또한 없으면 컴파일러가 자동으로 생성해 줍니다. 그러니 이제는 @~~~라고 적혀있으면 가독성의 문제로 있는것이 아니다! 라고 생각하시면 될 것 같습니다.

 

★Point! 상속을 받은 모든 자식은 부모타입이다!

-> 이는 캐스팅에서 자세히 다루도록 하겠지만 상속을 배우면서 명심하셔야 하는 내용입니다.

반응형