메소드 오버라이딩
은 부모 클래스의 메소드를 자식 클래스에서 재정의하여 사용하는 것을 의미합니다. 부모 클래스의 메소드가 자식 클래스에서 사용하기 완벽하지 않다면 재정의를 통해 자식 클래스에 어울리게 만들 수 있습니다.
지난번에 배운 메소드 오버로딩은 같은 이름의 함수를 매개변수 개수를 다르게하여 중복 정의하는 것을 의미했습니다.
public class Member {
protected String name;
protected Member() {}
public void printName() {
System.out.println("Member 클래스의 name 필드값: " + this.name);
}
}
public class Student extends Member {
private int grade;
public Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student("김사과", 1);
student.printName();
}
}
우리는 Member 클래스를 상속받은 Student 클래스를 인스턴스화하여 상속받은 printName()
메소드를 사용했습니다. 그리고 해당 메소드는 Member 클래스에 속한 메소드이기 때문에 프로그래밍 적으로는 어색하지 않습니다.
하지만 사용자입장에선 Student의 객체 메소드를 호출했는데 Member 객체의~라고 나오는 것은 그다지 자연스럽지 못한 메시지 출력이라고 생각이 됩니다. 이때 메소드 오버라이딩
을 통해서 printName을 재정의하여 자연스럽게 바꿔줄 수 있습니다.
메소드 오버라이딩
은 재정의하고자 하는 메소드의 선언부는 완전히 일치하게 작성하고 내부 코드만 다르게 만들어줘야 성립합니다.
public class Student extends Member {
private int grade;
public Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
@Override //Annotation
public void printName() {
System.out.println("Student 클래스의 name 필드값: " + this.name);
}
}
여기서 @Annotation
은 어노테이션이라는 기능인데 코드의 특정 기능을 알리기 위해 사용하는 일종의 주석입니다. (이 부분은 따로 다룰 예정이라 지금은 간단하게 넘어갑니다!)
여기서는 @Overrride
라고 표기함으로써 이 메소드가 오버라이딩된 메소드라고 컴파일러 등에 알리고 있습니다. 생략해도 괜찮지만 오류를 방지하는 역할을 하는만큼 가급적이면 명시해주는 것이 좋습니다.
재정의를 하면 부모 메소드의 메소드가 호출되는 것이 아니라 자식 메소드가 호출됩니다. 따라서 추가할 부분만을 작성하는 것이 아니라 부모 메소드의 모든 코드를 적은 후 추가해서 재정의를 해야합니다. 이때 부모 메소드가 거대한 메소드라면 일일이 다 적기가 난감하겠죠?
이럴 경우 super
를 사용합니다. 생성자에서도 배웠듯이 super
는 부모 클래스의 멤버를 호출합니다. 따라서 super.메소드()
를 하면 부모 클래스의 메소드를 호출할 수 있는거죠.
이 기능을 사용해서 중복된 부모 메소드는 super.메소드명()
으로 호출해서 코드 작성을 줄이고 추가할 부분만 넣는 식으로 재정의 코드를 줄일 수 있습니다.
예시를 들기 위해 위에서 작성한 재정의 메소드에 한 줄을 추가했습니다.
@Override
public void printName() {
super.printName(); //부모인 Member 클래스의 prinrName() 호출
System.out.println("Student 클래스의 name 필드값: " + this.name);
}