관리자 글쓰기
오버라이딩과 오버로딩
2016. 6. 15. 11:49 - Daybreak0_0

method overriding


1
2
3
4
5
public class Animal {
    public void eat() {
        System.out.println("Generic Animal Eating Generically");
    }
}
cs

1
2
3
4
5
class Horse extends Animal  {
    public void eat() {
        System.out.println("Horse eating hay, oats, " + "and horse treats");
    }
}
cs

- 슈퍼 클래스로부터 추상 메서드를 상속받은 실체 서브 클래스의 경우 그 메서드를 오버라이딩하여 실행할 코드를 구현해야 한다.
  그렇지 않으면 서브 클래스에서도 추상 메서드를 갖는 것이 되어 서브 클래스가 추상 클래스가 된다. 
  ** 추상 메서드는 반드시 오버라이딩 해야한다. 


- Animal의 모든 서브 클래스들은 각자 자신의 오버라이딩된 eat() 메서드를 가져야한다. 

- Animal 서브 클래스의 인스턴스를 슈퍼 클래스인 Animal 타입의 참조 변수로 참조하면, 그 참조를 통해 eat() 메서드를 호출했을 때,

  그 인스턴스가 속하는 서브 클래스의 eat() 메서드가 다형적으로 실행된다. 


1
2
3
4
5
6
7
8
class TestAnimals  {
    public static void main(String[] args) {
        Animal a = new Animal();
        Animal b = new Horse(); // Animal타입이지만 Horse 객체이다.
        a.eat(); // Animal의 eat()를 실행
        b.eat(); // Horse의 eat()을 실행
    }
}
cs


- Animal 타입의 참조를 통해서 Horse 객체의 메서드를 호출한다. 

- Animal 타입의 참조를 사용할 때는 Animal 클래스에 있는 메서드만 호출이 가능하다 ** 

- 컴파일러는 인스턴스 자신의 타입이 아닌 참조의 타입을 살피며, 런타임 시에는 인스턴스의 타입에 맞는 메서드가 다형적으로 실행된다.

  슈퍼 타입의 참조를 사용해서 그 슈퍼 타입의 서브 타입 인스턴스를 참조할 수 있다.

- 서브 클래스에서 오버라이딩된 메서드의 접근 변경자는 슈퍼 클래서 메서드의 접근 변경자보다 접근 범위가 같거나 더 넓어야 한다. (좁아질수 x)

  예, 슈퍼클래스의 메소드 접근 변경자가 public이면 서브 클래스에서 오버라이딩된 메서드의 접근 변경자를 protected로 할 수 x


## 오버라이딩한 메서드의 슈퍼 클래스 버전을 호출하고 싶다면?

- super 키워드 사용
- super 키워드는 인스턴스 메서드만 호출이 가능하다 (static 메서드는 오버라이드 할 수 없음)

## 오버라이딩을 잘못한 예

잘못 오버라이딩한 코드 

코드의 문제

private void eat() {   } 

슈퍼 클래스의 메서드보다 접근 변경자 범위가 좁다. 

public void eat( ) throws IOException {   } 

슈퍼 클래스 메서드에 선언하지 않은 checked 예외를 선언했다.

public void eat(String food) {  }

인자 목록이 다르므로 오버라이딩이 아닌 오버로딩이 되었다. 

public string eat( ) {   }

반환 타입이 다르므로 오버라이딩이 아니며, 인자 목록이 같으므로 오버로딩도 아니다. 



method overloading


- 하나의 클래스에서 같은 이름의 메서드들을 여러개 가질 수 있는데, 메서드 인자들은 달라야 한다. (반환타입은 같아도 되고 달라도 된다.)

- 인자들의 타입이나 개수가 다르면 컴파일러가 이름이 같더라도 알수 있기 때문이다. ==> 오버로딩된 메서드는 오버라이딩 메서드와 달리 실행할 메서드가 컴파일 시점에서 결정된다. 

- 인자의 타입이나 개수가 달라야 하지만, 타입과 개수가 같으면 순서만 달라도 된다.

- 오버로딩된 메서드들의 접근 변경자도 상관없다. (같든 다르든)


같아야 되는 것 

달라야 되는 것 

상관없음 

메서드 이름

인자의 타입 

반환 타입 

인자 개수

접근 변경자 

 

checked 예외



1
pubic void changeSize(int size, String name, float pattern) {  }
cs


1
2
3
public void changeSize(int size, String name) {  }
public int changeSize(int size, float pattern) {  }
public void changeSize(float pattern, String name) throws IOException {  }
cs





1
2
3
4
5
public class Animal {
    public void eat() {
        System.out.println("Generic Animal Eating Generically");
    }
}
cs

1
2
3
4
5
6
7
8
class Horse extends Animal  {
    public void eat() {
        System.out.println("Horse eating hay");
    }
    public void eat(String s) {
        System.out.println("Horse eating " + s);
    }
}
cs


## 오버로딩을 잘못한 예

오버로딩한 코드 

출력 결과

Animal a = new Animal(); 

a.eat();

Generic Animal Eating Generically

Horse h = new Horse(); 

h.eat(); 

Horse eating hay

Animal ah = new Horse(); 

ah.eat();

Horse eating hay

다형성이 구현된다.

- 참조 타입 (Animal)이 아닌

실제 객체 타입 (Horse)를 기준으로 메서드가 결정됨

Horse h3 = new Horse(); 

h3.eat("apples");

Horse eating hay

Animal a2 = new Animal();

a2.eat("apples");

컴파일 에러!

String을 받는 eat( ) 메서드가 Animal 클래스에 없다.

Animal a3 = new Horse();

a3.eat("Carrot");

컴파일 에러!
컴파일러는 참조 타입을 기준으로, 

String을 인자로 받는 eat() 메서드가 Animal 클래스에 있는지 찾는다. 없으므로 에러. 


## 오버라이딩과 오버로딩의 차이점


 

오버라이딩 

오버로딩 

 인자

반드시 같아야 한다.

반드시 달라야 한다. 

반환 타입

같아야 한다. 

같거나 다를 수 있다. 

예외

슈퍼 클래스의 오버라이딩되는 메서드에 선언한 예외보다 범위가 좁은 예외는 가능, 예외를 추가하거나 범위가 큰 예외를 선언할 수 없다. 

같거나 다를 수 있다. 

접근 변경자

범위가 더 좁은 접근 변경자를 지정할 수 없다. 

같거나 다를 수 있다. 

호출

해당 객체의 타입을 기준으로 런타임 시 결정 

참조 타입을 기준으로 컴파일 시에 결정 


'Java 정리' 카테고리의 다른 글

가비지 컬렉션  (0) 2016.12.19
CH2_ 올바른 값의 반환  (0) 2016.06.16
CH2_참조 변수 Casting  (0) 2016.06.16