Java에서 다형성이란 조상 타입의 참조 변수로 자손 타입의 객체를 다루는 것을 말한다. 다형성 참조 변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다. 따라서 자손 타입의 참조 변수로 조상 타입의 객체를 다룰 수는 없다.
- 부모클래스 변수명 = new 자손클래스();
package com.example1;
class Parent {
void method1() {
System.out.println("부모 클래스 method1");
}
}
// Child클래스는 Parent 클래스를 상속 받는다.
class Child extends Parent {
void method1() {
System.out.println("자식 클래스 method1");
}
void method2() {
System.out.println("자식 클래스 method2");
}
}
public class Example1 {
public static void main(String[] args) {
//부모 클래스 타입의 참조변수를 사용하여 자식 클래스의 객체를 생성한다.
Parent p = new Child();
//p의 실제 타입은 Child이므로, 자식 클래스의 method1이 호출된다.
p.method1(); // 자식 클래스 method1
// Parent 객체에 있는 데이터만 담기 때문에 method2를 사용할 수 없다.
// p.method2(); // 오류
}
}
참조변수의 형변환
사용할 수 있는 멤버의 갯수를 조절하는 방법으로, 참조변수의 형변환은 인스턴스에 영향을 끼치지 않는다. 조상과 자손 관계의 참조변수는 서로 형변환이 가능하다. 자손타입의 참조변수를 조상타입으로 형변환 하는 경우 (up-casting) 형변환을 생략할 수 있고, 조상타입의 참조변수를 자손타입으로 형변환 하는 경우 (down-casting) 형변환을 생략할 수 없다.
package com.example1;
class Parent {
void method1() {
System.out.println("부모 클래스 method1");
}
}
// Child클래스는 Parent 클래스를 상속 받는다.
class Child extends Parent {
void method2() {
System.out.println("자식 클래스 method2");
}
}
public class Example1 {
public static void main(String[] args) {
//부모 클래스 타입의 참조변수를 사용하여 자식 클래스의 객체를 생성한다.
Parent p = new Child();
//부모 클래스 타입의 p를 형변환을 통해서 자식 클래스로 변경해서
Child c = (Child)p;
//자식 클래스의 method2를 호출할 수 있다.
c.method2(); //자식 클래스 method2
}
}
instanceof 연산자
참조변수를 형변환하기 전에 형변환 가능여부 확인에 사용한다. 사용이 가능하면 true를 반환한다.
- 참조변수 instanceof 타입(클래스명)
public class Example1 {
public static void main(String[] args) {
//부모 클래스 타입의 참조변수를 사용하여 자식 클래스의 객체를 생성한다.
Parent p = new Child();
// 형변환 가능 여부 확인 후 형변환
if (p instanceof Child) {
//부모 클래스 타입의 p를 형변환을 통해서 자식 클래스로 변경해서
Child c = (Child) p;
//자식 클래스의 method2를 호출할 수 있다.
c.method2();
}
}
}
여러 종류의 객체를 배열로 다루기
조상타입의 배열에 자손들의 객체를 담을 수 있다. 배열에 객체를 담아 여러 종류의 객체를 같이 다룰 수 있다.
이 예제는 Vehicle이라는 부모 클래스를 생성하고, 이를 상속받는 여러 자식 클래스인 Car, Bicycle, Bus를 정의한 뒤 각 객체를 배열에 넣고 ride() 메서드를 호출하는 예시이다.
Vehicle (부모클래스)
class Vehicle{
void ride(){
System.out.println("탄다.");
}
}
Car, Bicycle, Bus (자식클래스)
class Car extends Vehicle{
@Override
void ride() {
System.out.println("차를 탄다.");
}
}
class Bicycle extends Vehicle{
@Override
void ride() {
System.out.println("자전거를 탄다.");
}
}
class Bus extends Vehicle{
@Override
void ride() {
System.out.println("버스를 탄다.");
}
}
배열에 넣어 각 객체의 ride()메서드 호출
public class Example1 {
public static void main(String[] args) {
//배열로 인스턴스 생성
Vehicle[] vehicles = new Vehicle[3];
//객체를 배열에 담기
vehicles[0] = new Car();
vehicles[1] = new Bicycle();
vehicles[2] = new Bus();
//배열에 담은 객체를 for문을 통해 사용
for(Vehicle vehicle : vehicles){
vehicle.ride();
}
}
}
<<전체 예제>>
package com.example1;
// 부모클래스
class Vehicle{
void ride(){
System.out.println("탄다.");
}
}
// 자식클래스
class Car extends Vehicle{
@Override
void ride() {
System.out.println("차를 탄다.");
}
}
class Bicycle extends Vehicle{
@Override
void ride() {
System.out.println("자전거를 탄다.");
}
}
class Bus extends Vehicle{
@Override
void ride() {
System.out.println("버스를 탄다.");
}
}
public class Example1 {
public static void main(String[] args) {
//배열로 인스턴스 생성
Vehicle[] vehicles = new Vehicle[3];
//객체를 배열에 담기
vehicles[0] = new Car();
vehicles[1] = new Bicycle();
vehicles[2] = new Bus();
//배열에 담은 객체를 for문을 통해 사용
for(Vehicle vehicle : vehicles){
vehicle.ride();
}
}
}
하이딩(Hiding)
자식 클래스가 부모 클래스의 static 메서드와 동일한 이름과 매개변수를 가진 static 메서드를 정의했을 때 발생한다. static 메서드의 경우 클래스(method area)에 저장 되기 때문에 참조 변수의 타입에 따라 어떤 메서드가 호출될지 결정된다.
즉, 부모 클래스의 static 메서드는 자식 클래스에서 가려지지만(hiding), 호출 될 때는 참조 변수 타입에 따라 부모 클래스의 static 메서드가 호출된다. static 메서드는 다형성의 영향을 받지 않으며 항상 참조 변수의 타입에 따라 결정된다.
package com.example1;
// 부모클래스
class Vehicle{
void ride(){
System.out.println("탄다.");
}
static void stop(){
System.out.println("Vehicle 클래스 : stop 메서드");
}
}
// 자식클래스
class Bus extends Vehicle{
@Override
void ride() {
System.out.println("버스를 탄다.");
}
//static 메서드를 자식 클래스에서 동일하게 정의함
static void stop(){
System.out.println("Bus 클래스 : stop 메서드");
}
}
public class Example1 {
public static void main(String[] args) {
Vehicle veh1 = new Bus();
veh1.ride(); // 버스를 탄다.
veh1.stop(); // Vehicle 클래스 : stop 메서드
// 참조 변수가 Vehicle이기 때문에 Vehicle의 static method가 호출됨
// 형변환을 통해서 참조 변수가 Bus일 경우
Bus bus1 = (Bus)veh1;
bus1.stop(); // Bus클래스 : stop 메서드
// 참조 변수가 Bus이기 때문에 Bus의 static method가 호출됨
}
}
'Backend > Java' 카테고리의 다른 글
Java 기초 문법 : 제네릭(generic) (0) | 2024.10.08 |
---|---|
JAVA : 레코드(Record)에 대해서 (0) | 2024.10.07 |
Java 기초 문법 : JVM 메모리구조 (0) | 2024.10.07 |
Java 기초 문법 : 인터페이스(interface) (1) | 2024.06.19 |
Java 기초 문법 : 제어자(modifier) (1) | 2024.06.13 |
Java 기초 문법 : 패키지, import문 (1) | 2024.06.13 |
Java 기초 문법 : this와 super() (0) | 2024.06.10 |
Java 기초 문법 : 클래스간의 관계 - 상속과 포함 (0) | 2024.06.09 |