다수의 class를 만들어야 하는데, 모든 class가 공통된 속성과 행동을 공유하는 경우라면 inheritance를 사용하여 효율적으로 코드를 작성할 수 있습니다. 정확히는 class 간의 관계가 "is a" 관계일 때 inheritance를 적용할 수 있습니다.
실생활에서 예를 들어보겠습니다. 동물과 고양이는 어떤 관계인가요? 고양이가 동물에 속하는 관계입니다. 즉, 고양이가 동물 (A cat is an animal)이라고 말할 수 있습니다. 이런식으로 class 간의 관계도 동물과 고양이와 동일한 관계라면 inheritance를 사용해주면 됩니다.
Class 상속을 하기 위해서는 extends keyword를 사용합니다.
1
2
3
4
5
6
|
//Volvo class를 만들 때 Car class 상속
//Car class가 가진 fields와 methods를 모두 Volvo class에서도
//사용할 수 있게됨.
public class Volvo extends Car{
}
|
cs |
이때 Car는 부모 클래스가 되고 Volvo는 자식 클래스가 됩니다. (Volvo 역시 Car 이기 때문에 예시로 적절하다고 생각하여 사용했습니다.)
Fields 상속받기
여기서 주의할 점은 부모 클래스에 parameter가 있는 constructor가 정의되어 있다면,
자식클래스에서는 이를 상속 받아야만 합니다. 상속은 Command + N 을 눌러 generate을 이용하면 됩니다.
원하는 constructor를 골라서 OK를 누르면 아래와 같이 상속이 됩니다.
1
2
3
4
5
|
public class Volvo extends Car {
public Volvo(int doors, int wheels, String model, String engine, String colour) {
super(doors, wheels, model, engine, colour);
}
}
|
cs |
보면 super 라는 keyword와 함께 Car class의 constructor가 생겼습니다. super가 해당 constructor를 호출하는 역할을 합니다.
Volvo는 Car class를 상속하기 때문에 Car가 가지고 있는 fields나 methods를 모두 사용할 수 있는 것입니다.
super vs super()
this와 this()가 클래스 본인의 variables과 constructor를 지칭하고 호출하는 도구였습니다.
super와 super()는 하위 클래스에서 상위 클래스의 variable을 지칭하고 상위클래스의 constructor 호출하는 도구입니다.
만일 상위 클래스와 하위 클래스에 동일한 이름의 variable이 있는데 하위 클래스에서 super를 생략하고 해당 variable을 사용한다면 compiler는 인스턴스 내부의 variable을 참조하게 됩니다.
그렇다면 Car class는 가지고 있지 않지만 Volvo class 만이 가진 독특한 특성들은 어떻게 추가할 수 있을까요?
Car class에 추가하던 방법 그대로 fields는 private keyword를 사용해서, methods는 public keyword를 사용해서 코드를 작성하면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
|
public class Volvo extends Car {
private boolean moonRoof;
private int touchScreen;
public Volvo(int doors, int wheels, String model, String engine, String colour, boolean moonRoof, int touchScreen) {
super(doors, wheels, model, engine, colour);
}
}
|
cs |
볼보에는 테블릿만큼 큰 터치스크린과 문루프가 들어있다고 해서 한 번 볼보만의 fields로 추가해보았습니다.
그리고 추가한 필드를 initialize 해주어야 하는데, 좀 전에 상속받은 constructor 내부에서 진행하면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Volvo extends Car {
private boolean moonRoof;
private int touchScreen;
public Volvo(int doors, int wheels, String model, String engine, String colour, boolean moonRoof, int touchScreen) {
super(doors, wheels, model, engine, colour);
this.moonRoof = moonRoof;
this.touchScreen = touchScreen;
}
}
|
cs |
이런 식으로 this.을 사용해서 initialize하면 되고, 파라미터도 추가해주면 됩니다.
자식 클래스 constuctor 역시 default 값을 설정해서 변동이 없는 값은 고정한 뒤 사용할 수도 있습니다.
Methods 상속받기
이렇게 Car class(부모클래스)의 fields는 모두 상속을 받았는데, methods는 어떻게 상속받으면 될까요?
Methods의 경우 constructor 설정과 같은 추가 작업을 할 필요가 없이 extends를 하면 자동으로 상속이 됩니다.
Main class로 가서 한 번 확인해보겠습니다.
1
2
3
4
5
6
7
8
|
public class Main {
public static void main(String[] args) {
Volvo myVolvo = new Volvo(4,1,"xc90","powerful engine","white",true,1);
myVolvo.getModel();
}
}
|
cs |
myVolvo라는 Volvo class를 이용한 object를 만들어 주었고, initialize까지 완료했습니다.
그리고 나서 moVolvo.을 써보면 Volvo class에는 작성하지 않았지만 Car class에는 들어있는 methods 리스트가 나오는 것을 확인할 수 있습니다.
한번 .getMode()을 사용해보면, Car class에 있는 .getModel() 함수를 호출하게 되는 것입니다.
Volvo class만이 가지는 methods를 정의해준다면 해당 methods는 Volvo class로 만든 objects만 사용할 수 있고 Car class로 만든 objects들은 사용할 수 없습니다. (부모의 method는 자식이 사용 가능하지만 자식의 methods는 부모가 사용할 수 없습니다. Fields도 마찬가지구요!)
-Method override
그렇다면 부모 클래스의 methods도 자식 클래스에 맞춰 커스터마이징이 될까요?
네 Method override를 사용하면 가능합니다.
Method override에는 조건이 몇 가지 있습니다.
1) Method name, parameter type, parameter name, parameter 수가 super class와 동일해야 합니다. Method block 안의 내용만 변경이 가능합니다.
2) 접근 제어자 범위가 상위 클래스의 method보다 같거나 넓어야 합니다.
테스트 해보기 위해 Car class에 move() 라는 method를 만들었습니다.
1
2
3
4
5
6
7
|
public class Car {
//...
public void move() {
System.out.println("Car is moving.");
}
}
|
cs |
그리고 Volvo class로 가서 move() method를 override 해보겠습니다.
Override를 할 때에도 command + N을 눌러 Generate 창을 열어 줍니다.
Generate 리스트 중에 Override Methods가 나와있고, 클릭하면 override가 가능한 함수 목록이 나타납니다.
그 중에서 저는 move() 함수를 override할 것이기 때문에 move()를 선택하였습니다.
그러면 아래와 같이 override 된 move method가 나타납니다.
1
2
3
4
5
6
7
8
9
10
|
public class Volvo extends Car {
//...
@Override
public void move() {
super.move();
}
}
|
cs |
Fields를 상속받을 때 처럼 super keyword가 붙어있음을 확인할 수가 있죠?
Volvo class의 move는 좀 다른 방식으로 만들고 싶다면, move() 코드 블록 안에 원하는 내용을 작성해주면 됩니다.
1
2
3
4
5
6
7
8
9
10
|
public class Volvo extends Car {
//...
@Override
public void move() {
System.out.println("Volvo is moving.");
}
}
|
cs |
저는 "Car is moving" 대신 "Volvo is moving" 이 print 되도록 변경하였습니다.
한 번 제대로 적용이 되었는지 Main class로 가서 확인해볼까요?
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Main {
public static void main(String[] args) {
Car car = new Car();
Volvo myVolvo = new Volvo(4,1,"xc90","powerful engine","white",true,1);
car.move();
System.out.println("-------------");
myVolvo.move();
}
}
|
cs |
Main에서 Car와 Volvo class로 각각 하나씩 objects를 만들어주고 move() method를 호출하였습니다.
콘솔창을 보니 내용이 제대로 잘 나온 것을 확인할 수 있었습니다.
지금까지 Class inheritance를 이용하면 어떠한 것들을 할 수 있는 지와 어떻게 사용하는 지 알아보았습니다.
1) Class inheritance를 사용하면 Class 간 부모-자식 관계를 만들게 되고,
부모 class가 가진 fields와 methods를 자식 class는 모두 접근하여 사용할 수 있습니다. (그 반대는 가능하지 않습니다.)
2) 뿐만 아니라 자식 Class는 본인만이 가지는 fields와 methods를 추가할 수도 있고 부모 class가 가진 methods를 override하여 커스터마이징 할 수도 있습니다.
3) 추가적으로 다형적 표현이 가능해지는데요, 다형적이란 하나의 객체가 여러 모양으로 표현될 수 있는 것을 의미합니다. 이와 관련해서는 polymorphism(다형성) 포스팅에서 좀 더 설명해드리고 있습니다.
다음번에는 inheritance 보다 좀 더 유연한 composition에 대해서 알아보겠습니다 ☺️
'Java' 카테고리의 다른 글
Class(5)-Encapsulation(캡슐화)란? 사용 방법과 이유 (0) | 2022.04.28 |
---|---|
Class(4)-Composition (2) | 2022.04.27 |
Class(2)-Constructor-set을 간편하게 (4) | 2022.04.25 |
Class(1)-Class란 & Class 사용하기 (0) | 2022.04.25 |
User Input 받는 방법 - Scanner사용 (0) | 2022.04.22 |