본문 바로가기
개발언어/Java : 자바

자바 쉽게 배우기 9 - 다형성

by 개발자D 2023. 1. 14.

다형성

다형성 polymorphism

객체지향 프로그래밍 언어는 다섯 가지의 특징을 가집니다. [캡슐화], [정보 은닉], [추상화], [상속성], [다형성] 이 5가지입니다.

[캡슐화] [정보은닉]은 접근 제어자를 설명드릴 때 한 번 나왔습니다. 캡슐화란 알약을 만들 때 여러 재료를 섞어 하나의 캡슐을 만드는 것에 비유할 수 있습니다. 자바의 클래스는 데이터(속성)와 데이터를 처리하는 함수(메서드)를 하나로 묶어줍니다. 속성과 메서드가 재료라고 할 때 클래스의 인스턴스는 하나의 캡슐이 되겠죠. 이렇게 캡슐에 담긴 재료들은 외부로부터 보호되며, 캡슐을 사용하는 사람들은 캡슐 안의 재료가 무엇인지 세세히 알 필요가 없습니다. 이렇듯 캡슐화를 사용하게 되면 보안성이 강화되고 여러 속성과 메서드가 묶여 있으므로 재사용이 용이해집니다.

[추상화]란 가장 핵심이 되는 공통적인 성질을 한 데 묶어내는 것을 의미합니다. 추상 클래스의 추상과 같은 의미를 갖습니다.

[상속성]은 지난 글에서 설명드린 '상속'이 가능하다는 특징입니다.

 

그렇다면 [다형성]은 무엇일까요? 다형성을 말 그대로 풀이하면 '여러 가지 형태를 가질 수 있는 능력'으로 해석됩니다. 다형성은 상속과 이어지는 개념입니다. 상위 클래스 타입의 참조변수는 하위클래스의 인스턴스를 참조할 수 있습니다. 쉽게 말해, 하위클래스의 인스턴스는 다양한 상위클래스의 타입으로 선언될 수 있습니다. 다양한 상위클래스라는 것은 다중상속을 의미하는 것이 아닌 상위 클래스의 상위클래스의 타입으로 선언되는 것이 가능하다는 의미입니다.

class Vehicle {
...
}

class Car extends Vehicle {
...
}

class Truck extends Car{
...
}

// Vehicle > Car > Truck

Vehicle vehicle = new Vehicle(); // 가능
Car car = new Car(); // 가능
Truck truck = new Trcuk(); // 가능
Car carTruck = new Trcuk(); // 가능
Vehicle vehicleTruck = new Truck(); // 가능
Truck truckCar = new Car(); // 불가능

하지만, 상위클래스 타입으로 선언된 참조변수는 사용할 수 있는 멤버가 제한적입니다. 자신이 상속해 준 멤버에 한해서만 접근할 수 있습니다.

 

그렇다면 만약 하위클래스에서 상위클래스의 메서드를 오버라이딩 했다면 상위클래스 타입으로 선언된 참조변수는 어떤 메서드를 호출하게 될까요? 상위클래스의 메서드일까요? 하위클래스의 메서드일까요?

정답은 오버라이딩된 하위클래스의 메서드입니다.

class Vehicle {
    void bbang() {
        System.out.println("bbang");
    }
}

class Car extends Vehicle {
    void bbang() {
        System.out.println("bbangbbang");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle vehicleCar = new Car();
        vehicleCar.bbang(); // bbangbbang
    }
}

 

[ 하위 클래스의 멤버 개수 >= 상위 클래스의 멤버 개수 ]를 기억하시나요? 하위 클래스의 멤버 개수는 상위 클래스의 멤버 개수보다 같거나 많을 수밖에 없습니다. 하위 클래스가 상위 클래스를 확장하기 때문이죠. 그렇기에 상위클래스의 인스턴스를 하위클래스의 타입으로 참조할 수는 없습니다.

 

상위클래스 타입의 인스턴스는 인스턴스가 실제로 소유하고 있는 멤버의 접근을 제한하는 것이지만,

하위클래스 타입의 인스턴스는 실제로 없는 멤버를 있는 것처럼 만들어야 하기 때문입니다. 불가능하죠. 

 


참조변수의 형변환

그렇다면 접근 제한을 풀기 위해서는 어떻게 해야 할까요? 바로 형변환을 이용해 주면 됩니다. 자바 쉽게 배우기 2 - 변수에서의 변수의 형변환을 기억하시나요? 기본형 뿐만 아니라, 참조형 변수도 형변환이 가능합니다.

참조 변수의 타입을 변환해 사용할 수 있는 멤버의 범위를 조절할 수 있습니다.

 

자동 형변환

하위 클래스 타입에서 상위 클래스 타입으로의 변환은 자동으로 이루어집니다.

 

강제 형변환

(형변환 할 클래스) 참조변수;
Vehicle vehicleTruck = new Trcuk(); // 1
(Car) vehicleTruck; // 2
(Truck) vehicleTruck; // 3

상위 클래스 타입에서 하위 클래스 타입으로의 변환은 위와 같은 형태로 강제 형변환이 가능합니다.

 

강제 형변환 조건

이때 참조변수가 참조하고 있는 인스턴스는 형변환 할 클래스의 인스턴스이거나 형변환 할 클래스의 하위 클래스의 인스턴스여야 합니다. 다시 말해, 형변환 할 클래스는 인스턴스의 클래스와 같거나 상위클래스여야 한다는 말입니다. 

 

접근 가능한 멤버의 수는 1 <=  2 <= 3  순으로 많아지게 될 것입니다.

instanceof 연산자

형변환을 하고 싶은데, 강제 형변환 조건에 해당하는지 모르겠을 때 어떻게 할까요? instanceof 연산자를 사용해 주면 쉽게 확인할 수 있습니다. 인스턴스가 확인할 클래스의 인스턴스이거나 확인할 클래스의 하위 클래스의 인스턴스에 해당할 때 결괏값으로 true를 얻습니다. 

참조변수 instanceof 확인할 클래스

 


참조변수와 인스턴스의 멤버

상위 클래스와 하위 클래스에 같은 이름의 멤버가 정의되어 있을 때 참조변수의 타입에 따라 접근되는 멤버가 달라집니다.

 

멤버 변수

참조 변수 타입의 멤버에 접근됩니다.

 

메서드

메서드는 이름이 같을 경우 오버라이딩 되기 때문에, 항상 실제 인스턴스의 메서드가 호출됩니다.


상속을 깊게 배우면서 헷갈리는 것들이 늘어나고 있습니다. 인스턴스, 참조 변수, 참조 타입, 상위클래스, 하위클래스에 대해 확실히 짚고 넘어가 봅시다. 다음 글에서는 추상클래스, 내부클래스, 인터페이스에 대해 설명드리겠습니다. 읽어주셔서 감사합니다.

 

자바 쉽게 배우기 10 - 다양한 클래스와 인터페이스

자바의 다양한 클래스 - 추상 클래스, 내부 클래스, 익명 클래스 추상 클래스 abstract class 자바 쉽게 배우기 8 - 상속과 제어자에서 abstract 키워드에 대해 설명드렸습니다. 추상클래스는 추상메서

devdharu.tistory.com