JAVA의 정석(2nd Editionm) (남궁 성 著) 238p~246p 를 참조해 코드를 작성했으며
개인적인 공부 내용을 적은 것이므로 오류가 있을 수 있습니다.
0. 들어가기에 앞서
오버라이딩은 상속(inheritance)와 관련이 깊은 내용이다. 따라서 공부하기 이전에 상속에 대한 내용을 충분히 숙지하기 바란다. (링크 : http://whatisthenext.tistory.com/19)
공부하면서 객체지향 프로그래밍은 "효율화"를 지향한다고 느꼈다.
효율화에 관점에서 본다면, 왜 상속이 필요한지, 왜 오버라이딩이 필요한지 조금이나마 알 수 있을 것 같다.
1. 오버라이딩(overriding)
조상 클래스로부터 상속받은 메서드(method) 내용을 자식 클래스에서 변경(변수 또는 메서드)하는 것.
over + writing과 발음이 비슷하니, "기존 메서드를 이용해 다시 쓰기"라고 생각하면 더 쉽다.
class Point {
int x;
int y;
String getLocation() { return "x :" + x + ", y : " + y; }
}
class Point3D extends Point {
int z;
String getLocation() { // getLocation()을 상속받음.return "x : " + x + ", y : " + y + ", z :" + z; }
}
위 예제에서
조상클래스는 class Point이다.
조상클래스의 메서드는 getLocation(){ return x, y, z}이다.
조상클래스로부터 상속받은 메서드 역시 getLocastion(){ 내용생략 }이다.
자손클래스는 class Point3D이다.
자손클래스가 상속받은 메서드는 getLocation() { 내용생략 } 이다.
자손클래스가 상속받은 메서드에 + z 를 추가해줌으로써 "오버라이딩"해주고 있다.
2 오버라이딩의 성립조건
위 예제를 통해 다시 살펴보자
이름, 반환타입, 매개변수가 모두 같다는 걸 알 수 있다. 이를 선언부가 일치한다고 한다.
(다른 말로는 메서드 시그니처(signiture, 서명) 이라고도 한다.)
단, 자손 클래스에서 오버라이딩할 때 조건이 있다.
1. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다. ※ public → protected → (default) → private순으로 접근범위가 좁아진다. ※ - 조상 클래스에 정의된 메서드 접근 제어자가 protected라면 자손 클래스에 정의된 메서드 접근 제어자는 protected나 public이어야 한다. 2. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다. - 조상 클래스에서 thorws IOExcpetion, SQLException 예외 2개를 예외한다면 자손 클래스에서 thorws IOException 또는 SQLException 중 1개만 예외할 수 있다. ※ 단, 예외의 최고조상 Exception 은 가장 많은 개수의 예외이므로 주의해야 한다. 3. 인스턴스메서드를 static메서드 또는 그 반대로 변경할 수 없다. |
3. 오버로딩 vs 오버라이딩
오버로딩(overloading) : 기존에 없는 새로운 메서드를 정의하는 것
오버라이딩(overriding) : 상속받은 메서드의 내용을 변경하는 것
4. super
super : 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
(즉, 슈퍼클래스를 참조)
※ this : 멤버변수와 지역변수의 이름이 같을 때 사용하는 참조변수. (즉, 서브클래스를 참조)
super를 이용해 조상 클래스로부터 상속받은 멤버를 참조
super를 이용해 조상 클래스의 메서드를
자손 클래스에서 오버라이딩(상속받은 메서드의 내용 변경)하는 경우 사용
5. super() - 조상 클래스의 생성자
생성자의 의미에 대해 다시 한 번 짚고 넘어가겠다.
생성자는 "인스턴스"가 생성될 때 호출되는 '인스턴스 초기화 메서드' 이다.
생성자는 "클래스" 내에 선언되며, 리턴값이 없다!
super() : 조상 클래스의 생성자를 호출하는데 사용
※ this() : 같은 클래스의 다른 생성자를 호출하는 데 사용
조상클래스의 생성자를 호출해야 하는 이유는, 자손클래스의 인스턴스를 생성하면
자손의 멤버 + 조상의 멤버가 합쳐진 하나의 인스턴스가 탄생된다.
따라서, 조상 클래스의 멤버를 사용할 수도 있으므로 조상의 멤버들이 먼저 초기화되어 한다.
자손클래스 Point3D의 생성자 첫 줄이 생성자를 호출하는 문장이 아니기 때문에
컴파일러 Point3D의 생성자 첫 줄에 super(); 자동으로 넣어준다.
그래서 코드 맨 위로 다시 올라가면 Point3D p3 = new Point3D(1,2,3,);으로
인스턴스를 생성하면, 생성자 Point3D(int x, int y, int z)가 호출되면서
위에서 넣어준 첫 줄 super();를 수행하게 된다.
흐름을 따라가면 super(); → (조상) Point클래스의 기본 생성자 Point()를 호출한다.
그러나 Point클래스에서 생성자 Point()를 정의하지 않았다. 따라서 컴파일 에러가 발생한다.
따라서 자손클래스 Point3D 클래스 생성자 첫줄에서 조상클래스의 생성자 Point(int x, int y)를 호출하도록
super(x, y); 를 추가하면 된다.
즉, 조상클래스의 멤버변수는 super을 이용해서 조상의 생성자에 의해 초기화 되도록 해야 한다.
'프로그래밍 > JAVA' 카테고리의 다른 글
[JAVA] 제어자(modifier) (0) | 2016.08.02 |
---|---|
[JAVA} 클래스 패스(Class Path)와 패키지(Package) (1) | 2016.08.01 |
[JAVA] 상속(Inheritance) (0) | 2016.08.01 |
[JAVA] 생성자(Constructor) (2) | 2016.07.21 |
[JAVA} 메서드 오버로딩(method overloading) (3) | 2016.07.21 |