오버라이딩이란 상속받은 메소드의 내용을 변경하는 것을 의미한다.
다음과 같이 자동차의 동작을 나타내는 클래스가 있다 가정하자.
public class Car {
boolean startupState;
float speed;
{// 초기화 블럭
this.startupState=false;
this.speed=0.0f;
}
void startUp() {// 시동걸기
this.startupState=true;
System.out.println("시동걸림.");
}
void drive(float speed) {// 이동
this.speed=speed;
System.out.println("속도: "+this.speed+"km");
}
void stop() {// 브레이크
this.speed=0.0f;
this.startupState=false;
System.out.println("시동끔.");
}
void horn() {// 경적
System.out.println("빵빵!! 피자빵!! 초코빵!! 크림빵!!");
}
}
이를 상속한 슈퍼카의 동작을 나타낸 클래스가 있다 가정하자
public class SuperCar extends Car {
int gearStage;
int mode;
void manualGearShift(int stage) {// 기어 변속
this.gearStage=stage;
System.out.println("기어 단수: "+ this.gearStage);
}
void driveMode(int mode) {// 운전모드
this.mode=mode;
switch(mode) {
case 1:
System.out.println("운전모드: 스포츠");
break;
case 2:
System.out.println("운전모드: 컴포트");
break;
default:
System.out.println("운전모드: "+ this.mode);
break;
}
}
}
차를 타고다니다 보니 이 슈퍼카의 경적이 일반 자동차의 경적과 똑같아 조금 더 멋있는 경적으로 바꾸고 싶을때는 어떻게 해야 할까?
이럴때 사용할 수 있는 것이 오버라이딩이다.
오버라이딩은 자동차 클래스에서 상속받은 메소드를 변경하는것이다.
즉, 부모클래스로부터 받은 메소드의 내용을 변경하는것
이 오버라이딩 이
다.
오버라이딩을 하기 위한 조건은 다음과 같다.
위의 조건을 만족한다면 오버라이딩을 할 수 있다.
위 조건들을 만족시키면서 슈퍼카의 경적을 바꾸기 위해서는 다음과 같은 메소드를 추가하면 된다.
void horn() {
System.out.println("부릉!!");
}
오버라이딩을 한 전체 코드는 다음과 같다.
Car
클래스
public class Car {
boolean startupState;
float speed;
{// 초기화 블럭
this.startupState=false;
this.speed=0.0f;
}
void startUp() {// 시동걸기
this.startupState=true;
System.out.println("시동걸림.");
}
void drive(float speed) {// 이동
this.speed=speed;
System.out.println("속도: "+this.speed+"km");
}
void stop() {// 브레이크
this.speed=0.0f;
this.startupState=false;
System.out.println("시동끔.");
}
void horn() {
System.out.println("빵빵!! 피자빵!! 초코빵!! 크림빵!!");
}
}
SuperCar
클래스
public class SuperCar extends Car {
int gearStage;
int mode;
void manualGearShift(int stage) {// 기어 변속
this.gearStage=stage;
System.out.println("기어 단수: "+ this.gearStage);
}
void driveMode(int mode) {// 운전모드
this.mode=mode;
switch(mode) {
case 1:
System.out.println("운전모드: 스포츠");
break;
case 2:
System.out.println("운전모드: 컴포트");
break;
default:
System.out.println("운전모드: "+ this.mode);
break;
}
}
void horn() {// 오버라이딩
System.out.println("부릉!!");
}
}
메인 메소드 클래스
public class Main {
public static void main(String[] args) {
SuperCar lamborghini = new SuperCar();// 람보르기니 ★겟☆또♧다♣제★
lamborghini.horn();
}
}
output
부릉!!
이와같이 오버라이딩을 하면 해당 메소드를 호출하면 오버라이딩된 메소드가 호출된다.
오버라이딩은 이름, 매개변수, 반환타입이 동일해야만 하므로, 작성하다 보면 실수가 많이 발생할 수 있다.
대표적으로 위의 예에서 horn()
을 hron()
과 같이 철자를 틀리거나, 매개변수를 horn(int mode)
와 같이 매개변수를 다르게 넣어서 오버라이딩이 안되는 경우 역시 존재할 수 있다. 그럴때는 어노테이션(Annotation)
을 사용해 예방할 수 있다.
어노테이션은 @
키워드를 작성하며, 오버라이딩 어노테이션은 @Override
으로 작성한다.
@Override// 어노테이션
void horn() {
System.out.println("부릉!!");
}
오버라이딩 어노테이션을 사용하면 오버라이딩이 안될경우 컴파일 에러를 발생시킨다.
@Override// 컴파일 에러!(오버라이딩 안됨)
void hron() {
System.out.println("부릉!!");
}
@Override// 컴파일 에러!(오버라이딩 안됨)
void horn(int mode) {
System.out.println("부릉!!");
}
오버로딩과 오버라이딩은 이름도 비슷하고, 같은 이름의 메소드를 사용한다는 점에서 쉽게 혼동될 수 있으나, 완전히 다른 개념이다.
오버로딩
은 새로운 기존의 메소드에 인자값, 반환값 등을 추가/삭제해 새로운 메소드를 정의하는것
이지만, 오버라이딩
은 상속받은 기존의 메소드의 내용을 변경하는것
이다.
예를 들어보자.
다음 원본 메소드가 있다고 가정하자.
void horn() {
System.out.println("부릉!!");
}
그렇다면 아래 메소드는 오버로딩인가? 아니면 오버라이딩인가?
String horn() {
return "부릉!!";
}
정답은 오버로딩
이다. 왜냐하면 반환값이 void
에서 String
으로 바뀌었기 때문이다.
그렇다면 다음 코드는 오버로딩인가? 아니면 오버라이딩인가?
void horn(int mode) {
System.out.println("부르릉!!");
}
이 역시 오버로딩
이다. 왜냐하면 인자값이 생겼기 때문이다.
마지막으로 다음 코드는 오버로딩인가? 아니면 오버라이딩인가?
void horn() {
System.out.println("빵빵!!");
}
정답은 오버라이딩
이다.
왜냐하면 메소드의 반환값, 이름, 매개변수가 같기 때문이다.
즉, 오버로딩과 오버라이딩의 차이는 메소드의 반환값, 매개변수의 변화 유무에 따라 결정된다.
이러한 내용은 면접 질문에도 나올 수 있기 때문에 반드시 알아두도록 하자.
소중한 정보 감사드립니다!