메소드 오버라이딩(method overriding): 슈퍼 클래스의 메소드를 서브 클래스에서 재정의
- 슈퍼 클래스에 있는 메소드로 목적하는 바를 이룰 수 없을 때 동일한 메소드를 서브 클래스에 다시 작성
- 슈퍼 클래스 메소드의 이름, 매개변수 타입, 매개변수 개수, 리턴 타입 등 모든 것을 동일하게 작성
- '슈퍼 클래스 메소드 무시하기' 혹은 '덮어쓰기'
- 오버라이딩된 메소드가 무조건 실행되는 동적 바인딩 발생

메소드 오버라이딩 사례

Line line = new Line();
line.draw();
- new Line()에 의해 생성된 객체에는 2개의 draw() 메소드가 존재
- 레퍼런스 line이 Line 타입이므로 컴파일러는 line.draw(); 실행 시 Line 클래스의 draw() 메소드를 호출
Shape shape = new Line(); //업캐스팅
shape.draw();
- new Line()에 의해 생성된 Line 객체에는 2개의 draw() 메소드가 존재
- 레퍼런스 shape이 Shape 타입이므로 shape.draw() 컴파일 시 컴파일러는 Shape 클래스에 draw() 멤버가 있는지 확인한 후 Shape의 draw() 호출
- shape.draw() 실행 시 shape이 가리키는 객체에 Shape의 draw를 오버라이딩한 Line의 draw() 존재
- Line의 draw() 실행
- 위 과정이 동적 바인딩

오버라이딩의 목적: 다형성 실현
- 오버라이딩은 슈퍼 클래스에 선언된 메소드를 각 서브 클래스들이 자신만의 내용으로 새로 구현하는 기능
- 상속을 통해 하나의 객체 지향의 다형성(하나의 인터페이스(=같은 이름)에 서로 다른 내용 구현) 실현
- 실행 시간 다형성 실현
오버라이딩의 제약 사항
1. 슈퍼 클래스의 메소드와 동일한 원형으로 작성
- 이름, 매개변수(타입과 개수), 리턴 타입 동일
2. 슈퍼 클래스 메소드의 접근 지정자보다 접근 범위를 좁혀 오버라이딩 불가
- 접근 지정자는 public>protected>default>private 순으로 접근 범위가 좁아짐
- 슈퍼 클래스에서 public로 선언된 메소드를 protected로 오버라이딩 할 수 없음
3. static이나 private, final로 선언된 메소드를 오버라이딩 할 수 없음
메소드 오버라이딩 활용
- 서브 클래스 개발자가 슈퍼 클래스의 특정 메소드를 새로 만들어 사용하고자 할 때
//예제 5-5 Shape, Line, Rect, Circle 클래스 활용
public class UsingOverride{
public static void main(String[] args){
//링크드 리스트로 도형 생성하여 연결
start=new Line(); //Line 객체 연결
last=start;
obj=new Rect();
last.next=obj; //Rect 객체 연결
last=obj;
obj=new Line(); //Line 객체 연결
last.next=obj;
last=obj;
obj=new Circle(); //Circle 객체 연결
last.next=obj;
//모든 도형 출력
Shape p=start;
while(p!=null){
p.draw();
p=p.next;
}
}
}

- start 변수는 링크드 리스트의 시작 레퍼런스 저장
- last는 링크드 리스트에 연결된 마지막 도형 객체의 레퍼런스 저장
- obj는 새로 생긴 도형 객체의 레퍼런스 저장
- start에서부터 연결된 모든 도형 객체를 방문하며 draw() 메소드 호출
동적 바인딩: 실행할 메소드를 실행 시(run time)에 결정
- 정적 바인딩: 실행 이전에 값 확정
- 자바에서는 동적 바인딩을 통해 오버라이딩된 메소드가 무조건 실행되게끔 함

Shape a = new Shape();
a.paint(); //paint()는 Shape의 draw()를 호출
Shape b = new Cirle();
b.paint(); //paint()는 Circle에서 오버라이딩한 draw() 호출
오버라이딩과 super
- 메소드가 오버라이딩되면 동적 바인딩에 의해 항상 서브 클래스에 오버라이딩한 메소드 호출
- super를 이용해 슈퍼 클래스의 멤버에 접근 가능
- super: 자바 컴파일러에 의해 지원되는 슈퍼 클래스에 대한 레퍼런스
- 컴파일러는 super의 접근을 정적 바인딩으로 처리
- super는 서브 클래스에서만 사용
name = "Circle"; //Circle 클래스의 name에 "Circle" 기록
super.name = "Shape"; //Shape 클래스의 name에 "Shape" 기록
super.draw(); //Shape 클래스의 draw() 호출, 정적 바인딩

오버라이딩 vs 오버로딩

예제 5-5 아래 코드의 실행 결과
class Shape{
public Shape next;
public Shape() {next=null;}
public void draw() {System.out.println("Shape");}
}
class Line extends Shape{
public void draw() {System.out.println("Line");}
}
class Rect extends Shape{
public void draw() {System.out.println("Rect");}
}
class Circle extends Shape{
public void draw() {System.out.println("Circle");}
}
public class MethodOverridngEx {
static void paint(Shape p) {
p.draw();
}
public static void main(String[] args) {
Line line=new Line();
paint(line);
paint(new Shape());
paint(new Line());
paint(new Rect());
paint(new Circle());
}
}
예제 5-6 게임에서 대포를 구현하기 위해 Cannon 클래스를 작성
- 무기를 표현하는 Weapon 클래스를 만들고 살상능력을 리턴하는 fire() 메소드를 작성하면 다음과 같다.
class Weapon{
protected int fire() {
return 1; //무기는 기본적으로 한 명만 공격
}
}
- Cannon 클래스는 Weapon을 상속
- Cannon은 10명을 공격하므로 fire() 메소드를 이에 알맞게 오버라이딩
- main()을 작성하여 테스트
'java > 개념' 카테고리의 다른 글
인터페이스(interface) (0) | 2024.05.23 |
---|---|
추상 클래스 (0) | 2024.05.23 |
업캐스팅과 다운캐스팅(+instanceof 연산자) (0) | 2024.05.22 |
상속과 생성자 (0) | 2024.05.21 |
상속과 접근지정자 (0) | 2024.05.21 |