이 포스팅은 아래의 내용을 포함하고 있습니다.
1. 다형성이란
2. 참조변수의 형변환
3. instanceof 연산자
4. 예제
1. 다형성이란?
- 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것
- 다룰 수 있는 멤버 개수가 다르다( 예제에서 확인)
- 조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있지만 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수 없음
- 메서드를 오버라이딩한 경우
자손클래스의 메서드가 호출됨
2. 참조변수의 형변환
- 서로 상속, 구현관계에 있는 타입간 형변환이 가능하다.
자손-> 조상 형변환 (업캐스팅): 형변환 생략 가능
조상-> 자손 형변환 (다운캐스팅): 형변환 생략 가능
(예제)
<조상클래스>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package sec01_exam;
//조상클래스 멤버갯수: 4개
public class Car {
String color;
int door;
//운전하는 기능
void drive() {
System.out.println("drive, Brrr~");
}
//멈추는 기능
void stop() {
System.out.println("stop!!");
}
}
|
cs |
<자손클래스>
1
2
3
4
5
6
7
8
9
10
11
|
package sec01_exam;
//extends는 상속관계(직접적 관계), Ambulance멤버의 갯수는 5개
public class Ambulance extends Car{
//사이렌 기능
void siren()
{
System.out.println("삐융삐융~");
}
}
|
cs |
<자손클래스>
1
2
3
4
5
6
7
8
9
|
package sec01_exam;
//extends는 상속관계(직접적 관계), FireEngine클래스의 멤버는 몇개? 5개
public class FireEngine extends Car{
void water() {
System.out.println("water!!");
}
}
|
cs |
<실행클래스>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package sec01_exam;
public class CastingEx {
public static void main(String[] args) {
Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
fe.water();
//업캐스팅(자손-> 조상) 형변환 생략 가능, 다룰 수 있는 멤버 개수 줄어든다.
car = fe;//필드의 다형성
//car.water(); 예외 발생, car의 근본이 Car이기 때문
fe2 = (FireEngine)car; //다운캐스팅 . 형변환 생략 불가능. 다룰 수 있는 멤버 개수 늘어남
fe2.water();
}
}
|
cs |
car은 Car(조상)의 인스턴스이고 fe는 FireEngine(자손)의 인스턴스인데
자손의 객체를 조상에 대입하고 있습니다.
다형성때문에 가능합니다.
이 부분을 보시면 Car클래스에는 water가 없기떄문에 사용할 수 없습니다.
자손은 조상의 멤버를 모두 사용할 수 있지만, 조상은 자손의 멤버를 사용하지 못합니다.
근본이 Car이기에 Car에 있는 멤버만을 사용할 수 있습니다.
fe2 에 car을 집어넣고 있는데 형변환을 해서 집어넣고 있습니다.
car은 조상, fe2는 자손이므로 조상타입에서 자손타입으로 형변환 하는 것 즉, 다운 캐스팅이므로 형변환 코드를 생량할 수 없습니다.
fe2는 근본이 FireEngine이기에 water메서드를 사용할 수 있습니다.
<실행결과>
<실행클래스2>
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
|
package sec01_exam;
public class CastingEx2 {
public static void main(String[] args) {
Car car = new Ambulance();
FireEngine fe = new FireEngine();
Ambulance al = new Ambulance();
Car car2 = null;
fe.drive();
fe.water();
//형변환은 상속관계에서만 성립한다.
//fe= (FireEngine)al;
//car = fe;
//컴파일은 ok, 실행시 에러가 발생 (ClassCastException발생)
//fe= (FireEngine)car;
al = (Ambulance)car;
al.siren();
fe.water();
car2 = fe;
car2.drive();
}
}
|
cs |
다형성의 개념으로 조상으로 자손의 인스턴스를 생성할 수 있습니다.
상속 관계가 아니기에 형변환은 불가능합니다.
상속관계이므로 형변환이 가능하며, 다운캐스팅을 하고 있습니다.
<출력결과>
3. instanceof 연산자
실제 형변환이 가능한지를 알아볼때 쓰는 것이 유용하다.
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
|
package sec02_exam;
class Car{}
class FireEngine extends Car{}
class Ambulance extends Car{}
public class InstanceOfEx1 {
public static void main(String[] args) {
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
Object obj = fe;//업캐스팅
Car car = fe; //업캐스팅
//instanceof 연산자의 결과가 참이면 형변환이 가능하다
if (fe instanceof FireEngine) {
System.out.println("This is a FireEngine instance");
}
if (fe instanceof Car) {
System.out.println("This is a Car instance");
}
if (fe instanceof Object) {
System.out.println("This is a Object instance");
}
//아래 예외가 발생하는 이유는?FireEngine과 Ambulance는 아무런 관계가 없다
// if (fe instanceof Ambulance) {
// System.out.println("This is a Ambulance instance");
// }
}
}
|
cs |
fe instanceof FireEngine
은 fe가 FireEngine의 객체냐? 라고 묻는 것입니다.
fe instanceof Car
은 fe가 Car의 인스턴스냐? 라고 묻는 것입니다.
Car이 조상이므로 true입니다.
fe instanceof Object
는 fe가 Object의 인스턴스냐? 라고 묻는 것입니다.
Object가 조상이므로 true입니다.
<출력결과>
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
|
package sec02_exam;
//하나의 java파일에는 public이라는 제어자는 반드시 하나만 있어야 합니다.
//조상클래스
class Parent
{}
//자손클래스
class Child extends Parent
{}
public class InstanceOfEx2 {
public static void main(String[] args) {
//parentA 참조변수는 필드의 다형성이 적용된 코드.
Parent parentA = new Child();
method(parentA);
method(new Child());
Parent parentB = new Parent();
method(parentB);
method(new Child());
}
public static void method(Parent parent) {//Parent 와 자손타입 다 들어올 수 있음
if(parent instanceof Child) { //왼-> 오 업캐스팅되면 true, 다운 캐스팅 되면 false
//우측에 조상이 와야함
//서로 상속 관계에 있어서 instanceof연산자의 결과가 true이므로
//강제캐스팅이 가능.
Child child = (Child)parent;
System.out.println("Child로 변환 성공");
}
else {
System.out.println("Child로 변환 실패");
}
}
}
|
cs |
이 부분을 보시면 method의 매개변수로 Parent를 받고 있습니다.
그러면 매개변수로는 Parent나 Parent의 자손클래스의 객체가 올 수 있습니다.
매개변수로 받은 객체가 instanceof Child냐고 묻습니다.
맞다면 child객체를 생성해서 Child로 형변환을 해줍니다.
여기서 보시면 parentA는 Child로 객체 생성했으니 true
두번째는 new Child를 넘겼으니 당연히 true
세번째는 parentB가 Parent의 객체이므로 false입니다.
<출력결과>
'JAVA > java 이론' 카테고리의 다른 글
[자바JAVA]인터페이스 / 상속/ 구현/다형성/ default메서드/static메서드 (0) | 2020.10.29 |
---|---|
[자바JAVA] 추상클래스, 추상 메서드 abstract class (0) | 2020.10.28 |
[자바JAVA]제어자 modifier / 접근 제어자/ 제어자의 조합 (0) | 2020.10.21 |
[자바JAVA] 싱글톤 디자인 패턴 (0) | 2020.10.20 |
[자바JAVA] 메서드 오버라이딩 (0) | 2020.10.19 |