[Java] 상속
이번 포스팅은 많이 늦었네요 ㅎㅎ; 죄송합니다 다름이 아니라 이번에 부산 여행을 갔다 와서 좀 늦었습니다.
상속에 대해서 알아보겠습니다!
상속(inheritance)
1. 기존에 선언된 클래스의 필드를 새롭게 만들 클래스의 필드로 그대로 가져오고 싶을 때 사용합니다.
2. 여러 클래스 선언시 필드가 겹치는 경우, 부모 클래스를 먼저 선언하고 공통 필드를 묶어서 상속해줍니다.
자, 우리가 쓰고 있는 핸드폰을 봅시다. 지금 5G시대죠? 이제 6G개발도 되고있다는 얘기가 있지만.. 처음에 우리가 쓰던 핸드폰은 2G 폴더폰이었습니다. 그리고 3G핸드폰이 개발되고 4G, 그리고 지금의 5G핸드폰을 사용하고있습니다. 그렇다면 상식적으로 핸드폰 세대가 향상 될수록 전에 있던 기능들에 더해 새로운 기능들이 생겨나고 있죠. 그러면 새로운 세대가 나올 때마다 모든 기능을 새로 만들라고 한다면 모든 개발자들이 퇴사하겠죠?
그래서 있는 기능이 상속입니다. 원래 있던 코드들을 그대로 옮겨서 사용하고 그위에 다른 특정한 코드를 얹어서 사용하는거죠. 이것을 상속이라고 합니다.
상속 문법
class A{
A필드
}
class B extends A{
A, B필드
}
A : 부모 클래스, 상위 클래스, 슈퍼 클래스, 기반 클래스
B : 자식 클래스, 하위 클래스, 서브 클래스, 파생 클래스
문법은 먼저 기존에 있던 부모 A클래스에 있는 A필드가 있고 이것을 상속하려 한다면, 자식 클래스 B를 만들고 그 이름 옆에 extends A라고 적어주시면 B클래스에 A클래스 필드도 고스란히 들어갑니다. 따라서 B클래스에서 지역이 다른 A클래스 코드들을 사용할 수 있다는 뜻이죠.
super()
자식 클래스 타입의 객체로 부모 필드에 접근할 수 있습니다.
하지만 자식 생성자만 호출하기 때문에, 자식 필드만 메모리에 할당된다고 생각하지만 사실 자식 생성자에는 항상 부모생성자를 호출하며, 자식 생성자 호출 시 부모와 자식 필드 모두 메모리에 할당됩니다.
이 때 부모 생성자를 부르는 방법은 super()를 사용하는 것입니다.
이제 한번 만들어봅시다!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A{
public A() {
System.out.println("부모 생성자 호출");
}
int aData = 100;
void printAData() {
System.out.println(aData);
}
void printData() {
System.out.println(aData);
}
}
class A를 만들어봤습니다. 직접생성자를 선언하고 그 생성자가 사용이 된다면 “부모 생성자 호출”이라는 출력메소드를 넣었습니다.
그리고 int타입 aData변수를 만들어서 100값을 초기값으로 주었고요. void메소드 2개를 만들고 둘다 변수 aData를 출력하도록 하였습니다.
그 다음엔 자식 클래스를 만들어보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class B extends A{
public B() {
super();//생략이 가능하고, 생략 시 컴파일러가 자동으로 넣어준다.
System.out.println("자식 생성자 호출");
}
int bData = 10000;
int getAData() {
return aData;
}
int getBData() {
return bData;
}
}
A를 상속하는 B클래스를 만들었습니다. 이 역시 직접생성자를 선언했는데요, 먼저 super메소드로 부모 클래스에 접근할 수 있도록 하였습니다. 생략도 가능합니다. 그리고 생성자가 사용이 된다면 “자식 생성자 호출”이라는 문구를 출력하는 메소드도 넣었습니다. 그리고 bData라는 정수타입 변수를 선언하여 10000값을 초기값으로 넣었습니다. 그리고 정수타입 메소드 2개를 넣고 reteurn값은 각각 aData, bData로 했습니다!
이제 메인 클래스를 보겠습니다.
1
2
3
4
5
6
7
public class InheritanceTest {
public static void main(String[] args) {
B b = new B();
b.printData();
System.out.println(b.getAData());
}
}
먼저 메인 클래스에서는 B클래스 생성자만 사용했습니다. 그리고 A클래스에 있는 필드 printData()메소드를 b클래스에서 사용을 했습니다.
그리고 B클래스에서 A클래스에 있는 변수를 리턴하는 메소드를 출력해보았습니다.
신기하죠? 자식생성자만 사용했는데도 부모 생성자까지 사용이 되었습니다. 당연히 부모 클래스에 있는 필드들을 사용하기 위해서는 생성자가 사용이 되어야하겠죠? 따라서 부모클래스에 있는 메소드도 사용이 가능하고 자식클래스에 있는 메소드가 부모클래스에 있는 변수를 사용할 수 있었습니다.
이제는 자식클래스에서 부모클래스를 사용하는 방법을 알아봤는데요, 만약 자식클래스에도 부모클래스에 있는 필드와 이름이 같다면, 그리고 그 자식 클래스에서는 그 필드를 사용해야한다면 어떻게 부모클래스에 있는 필드를 무시할 수 있을까요? 그것을 해결하기 위해 오버라이딩을 배워보겠습니다.
다형성(polymorphism)
1. 오버로딩
2. 오버라이딩(재정의)
부모 필드에서 선언한 메소드를 자식 필드에서 수정하고자 할 때 재정의를 해야 합니다.이는 자식에서 부모 필드의 메소드와 동일한 이름으로
선언하는 것입니다. 부모 필드가 메모리에 먼저 할당되고 a라는 메소드가 먼저 올라갑니다. 이 때 자식 필드가 메모리에 할당되면서 재정의한 a라는 메소드가 새롭게 만들어지는 것이 아니라, 기존에 있던 a메소드 저장소에 새롭게 재정의한 소스코드의 주소가 덮어 씌워지게 됩니다. 따라서 자식 객체로 a메소드에 접근하면 자식 필드에서 재정의한 소스코드의 내용이 읽히게 됩니다.
설명은 어려워 보이지만 사실 그렇게 어려운 개념은 아닙니다.
1
2
int a = 100;
a=200;
이런식으로 정수타입 a를 100으로 초기값을 주어 선언하고 그다음에 대입연산자로 a에 200을 넣는다면, 그다음 a를 출력하면 어떤 값이 나올까요?? 당연히 200이죠. 오버라이딩도 이와 같은 개념입니다. 이름이 같은 두개의 필드가 부모, 자식 클래스에 있다면 나중에 자식 클래스에 있는 필드가 저런 식으로 재정의 되어 사용이 되는겁니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Car{
String brand;
String color;
int price;
public Car() {;}
public Car(String brand, String color, int price) {
super();
this.brand = brand;
this.color = color;
this.price = price;
}
void engineStart() {
System.out.println("열쇠로 시동 켜기");
}
void engineStop() {
System.out.println("열쇠로 시동 끄기");
}
}
class SuperCar extends Car{
String mode;
@Override
void engineStart() {
System.out.println("음성으로 시동 킴");
}
void openRoof() {
System.out.println("썬루프 열림");
}
void closeRoof() {
System.out.println("썬루프 닫힘");
}
}
public class Road {
public static void main(String[] args) {
SuperCar ferrari = new SuperCar();
ferrari.engineStart();
ferrari.openRoof();
}
}
통으로 가져왔습니다. Car라는 부모 클래스와 SuperCar라는 자식클래스를 만들었는데요, 슈퍼카에서 열쇠를 시동을 켠다는 것은 좀 알어울리겠죠? 그래서 슈퍼카클래스에서는 engineStart를 “음성으로 시동 킴”이라는 문구를 적었습니다. 그런데 engineStart는 부모클래스에도 있죠? 그래서
메소드를 입력하기 전에 @Override 를 적었습니다. 뜻은 무시하다입니다. 따라서 이 코드 뒤에 필드가 부모클래스와 이름이 같다면 부모클래스의 필드는 자식 클래스의 필드로 재정의 되어 사용이 됩니다. 이로써 상속을 하여도 강제적으로 전체만 할 수있는 것이 아니라, 선택적으로도 가능하답니다!
이번시간에는 상속에 대해서 배워보았습니다!
Comments powered by Disqus.