[Java기본]가상 함수(메서드)란?
목표
문제
일반적으로 상위 클래스 타입에 하위 클래스의 인스턴스타입이 할당되면 하위 클래스에만 존재하는 메서드들은 사용할 수가 없다.
그런데 다형성(참조변환)으로 인해 상위 클래스 타입에 하위클래스의 인스턴스가 들어있고 같은 이름의 메서드가 존재할때는, 오버라이딩 된 메서드가 호출이 된다.
어떻게 이런 구조가 가능한 것일까? 가상메서드를 이해하며 오버라이딩에 대해 더 알아보자.
정리
가상함수란
Java에서 상속하는 클래스 내에서 같은 시그니처(메서드명, 매개변수, 리턴형)의 함수로 오버라이딩 될 수 있는 함수 또는 메소드를 말한다.
어떻게 오버라이딩을 동작 시키는 것일까?
일반적으로 static이 아닌 메서드는 객체가 생성될 때 메서드 영역에 생성된다. 그리고 가상 함수는 가상함수 테이블(virtual function table) 이라는 구조로 함수의 주소를 저장하고 있다.
객체가 생성 되는 시점은 Runtime 시점으로 인스턴스의 타입을 결정지을 수 있다. 이때 재정의 된 메서드가 있을 경우, JVM이 가상 함수 테이블에서 메서드 주소를 이용하여 상위 클래스의 메서드가 아닌 인스턴스의 타입인 하위 클래스의 메서스(재정의 된 메서드)를 가져온다.
본문
Java 에서는 상위클래스와 하위클래스의 메서드 이름이 같을 때 오버라이딩 기능을 제공합니다. 아래 예시를 통해 확인해 봅시다.
상위클래스 Customer
class Customer {
void calPrice(){
System.out.println("상위클래스에서 계산한 가격입니다.");
}
void showCustomerInfo(){
System.out.println("상위클래스에서 실행된 고객 정보 입니다.");
}
}
하위 클래스 VipCustomer
public class VipCustomer extends Customer {
private String VipId = "1324";
void calPrice(){
System.out.println("하위클래스에서 계산한 가격입니다.");
}
String getVipId(){
return VipId;
}
}
실행 파일
public class Main {
public static void main(String[] args) {
Customer customer = new VipCustomer();
customer.calPrice();
customer.showCustomerInfo();
// customer.getVipid(); // 컴파일 에러
}
}
/* 출력 결과
하위클래스에서 계산한 가격입니다.
상위클래스에서 실행된 고객 정보 입니다.
*/
하위 클래스의 인스턴스를 가진 상위 클래스 타입의 참조변수는 하위 클래스의 메서드(getVipid())를 사용하지 못한다.
하지만 같은 이름으로 하위클래스에서 재정의된(오버라이딩 된) calPrice() 는 하위 클래스 인스턴스 객체 타입에 존재하는 메서드를 호출한다.
객체지향 프로그래밍에서는 위에서 말한 오버라이딩 활용하여 하나의 클래스를 여러 클래스가 상속을 받았을 경우, 각각의 상속된 하위클래스의 인스턴스의 함수가 호출되도록 하여 다형성(polymorphism)을 구현할 수 있다.
그런데 어떻게 이런 일이 가능한 것일까?
가상 함수
정의
객체 지향 프로그래밍에서 가상 함수(virtual function 또는 virtual method)는 상속하는 클래스 내에서 같은 시그니처(메서드명, 매개변수, 리턴형)의 함수로 오버라이딩 될 수 있는 함수 또는 메소드를 말한다.
그리고 Java에서는 항상 상속 관계에서는 가상 함수가 생성되고 동작하도록 규정하고 있다.
어떻게 동작할까?
일반적으로 static이 아닌 메서드는 객체가 생성될 때 메서드 영역에 생성된다. 가상 함수는 가상함수 테이블(virtual function table) 이라는 구조로 함수의 주소를 저장하고 있다.
객체가 생성 되는 시점은 Runtime 시점으로 인스턴스의 타입을 결정지을 수 있다. 이때 재정의 된 메서드가 있을 경우, JVM이 가상 함수 테이블에서 메서드 주소를 이용하여 상위 클래스의 메서드가 아닌 인스턴스의 타입인 하위 클래스의 메서스(재정의 된 메서드)를 가져온다.