7.2 오버라이딩(Overriding)
1. 오버라이딩(overriding)이란?
- 조상 클래스로부터 상속받은 메서드의 내용을 상속받는 클래스에 맞게 변경하는 것을 의미한다.
- 상속받은 조상 메서드를 자신에 맞게 변경하는 것
class Point{
int x;
int y;
// 받은 좌표를 문자열로 얻는 메소드
String getLocation(){
return "x: " + x + ", y : "+ y;
}
}
class Point3D extends Point{
int z;
//선언부는 변경 불가, 구현부{ }는 변경 가능
String getLoString(){ //오버라이딩 z를 포함시켜 고치는 것
return "x: " + x + ", y : "+ y+", z : " + z;
}
}
class MyPoint3{
int x;
int y;
String getLocation(){
return "x: " + x + ", y : "+ y;
}
}
class MyPoint3D extends MyPoint3{
int z;
String getLocation(){ //오버라이딩
return "x: " + x + ", y : "+ y + ", z : " + z;
}
}
public class overrideTest1 {
public static void main(String[] args) {
MyPoint3D p = new MyPoint3D();
p.x =3 ;
p.y = 5;
p.z = 7;
System.out.println(p.getLocation());
}
}
<조상으로부터 상속 받은 내용을 Overriding 한 코드>
class MyPoint3_2 extends Object{
int x;
int y;
//Object 클래스의 toString()을 오버라이딩
public String toString(){
return "x: " + x + ", y : "+ y;
}
}
public class overridingTest2 {
public static void main(String[] args) {
MyPoint3_2 p = new MyPoint3_2();
p.x=3;
p.y=5;
System.out.println(p.toString());
}
}
<오브젝트 클래스를 오버라이딩한 코드>
class MyPoint3_2 extends Object{
int x;
int y;
//Object 클래스의 toString()을 오버라이딩
public String toString(){
return "x: " + x + ", y : "+ y;
}
}
public class overridingTest2 {
public static void main(String[] args) {
MyPoint3_2 p = new MyPoint3_2();
p.x=3;
p.y=5;
//System.out.println(p.toString());
System.out.println(p);
}
}
<오브젝트 클래스를 오버라이딩한 코드 2 (더 간략하게)>
class MyPoint3_2 extends Object{
int x;
int y;
MyPoint3_2(int x, int y){
this.x = x;
this.y = y;
}
//Object 클래스의 toString()을 오버라이딩
public String toString(){
return "x: " + x + ", y : "+ y;
}
}
public class overridingTest2 {
public static void main(String[] args) {
MyPoint3_2 p = new MyPoint3_2(3,5);
System.out.println(p);
}
}
<오브젝트 클래스를 오버라이딩한 코드 3>
2. 오버라이딩의 조건
① 선언부가 같아야 한다. (이름, 매개변수, 리턴타입)
② 접근제어자를 좁은 범위로 변경할 수 없다 (접근제어자 - public, protected, private, default)
- 조상의 메서드가 protected라면, 범위가 같거나 넓은 protected나 public으로만 변경할 수 있다.
③ 조상클래스의 메서드보다 많은 수의 예외를 선언할 수 없다. - 8장에서 배움 외우기
import java.io.IOException;
import java.sql.SQLException;
class Parent{
void parentMethod() throws IOException, SQLException {
// ...
}
}
class Child extends Parent {
void parentMethod() throws IOException{
}
}
class Child2 extends Parent {
void parentMethod() throws Exception {
}
}
3. 오버로딩 VS 오버라이딩
오버로딩(Overloading) - 기존에 없는 새로운 메서드를 정의하는 것(new) ---> 상속과 관계 없음
오버라이딩(Overriding) - 상속받은 메서드의 내용을 변경하는 것(change, modify) ---> 상속과 관계 있음
class Parent{
void parentMethod() {
}
}
class Child extends Parent {
void parentMethod(){ } // 오버라이딩
void parentMethod(int i) { } // 오버로딩
void childMethod() {} // 오버로딩
void childMethod(int i) //에러!! 중복정의
void childMethod() {}
}
둘은 이름만 비슷하고 전혀 관련이 없다.
4. Super - 참조변수(1)
- this : 인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어 있고 모든 인스턴스 메소드에 지역변수로 숨겨진 채로 존재한다. 또한 this는 지역변수와 인스턴스변수 구별에 사용된다.
-super : this와 같다. 조상의 멤버와 자신의 멤버를 구별하는 데 사용한다. static 메서드에서는 사용불가하다.
class Parent{
int x = 10;
}
class Child extends Parent{
int x = 20;
void method(){
System.out.println("x="+x);
System.out.println("this.x="+this.x);
System.out.println("super.x="+super.x);
}
}
4. Super - 참조변수(2)
▶ this - 인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어있다. 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재한다.
▶ super - this와 같다. 조상의 멤버와 자신의 멤버를 구별하는 데 사용한다.
super와 this가 다른 주소를 가리키는 경우
//참조변수 super
public class super1 {
public static void main(String[] args) {
Child c = new Child();
c.method();
}
}
class Parent {int x = 10;}
class Child extends Parent{
int x = 20; //this.x
void method() {
System.out.println("x=" + x); //20
System.out.println("this.x=" + this.x); //20 자기 멤버
System.out.println("super.x=" + super.x); //10 조상멤버
}
}
super와 this가 같은 주소를 가리키는 경우
//참조변수 super
public class super2 {
public static void main(String[] args) {
Child2 c = new Child2();
c.method();
}
}
class Parent2 {int x = 10;} // super.x this.x 둘 다 가능
class Child2 extends Parent2{
void method() {
System.out.println("x=" + x); //10 자신의 x가 없어서 x는 조상 멤버
System.out.println("this.x=" + this.x); //10 조상멤버
System.out.println("super.x=" + super.x); //10 조상멤버
//x가 조상멤버에 하나밖에 없기 때문에 this와 super가 같은 곳을 가르킨다.
}
}
4. super( ) - 조상의 생성자(1)
- 자손클래스의 인스턴스를 생성하면, 자손의 멤버와 조상의 멤버가 합쳐진 하나의 인스턴스가 생성된다.
- 조상의 멤버들도 초기화되어야 하기 때문에 자손의 생성자의 첫 문장에서 조상의 생성자를 호출해야 한다.
Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에는 생성자(같은 클래스의 다른 생성자 또는 조상의 생성자)를 호출해야 한다.
그렇지 않으면 컴파일러가 자동적으로 'super( );'를 생성자의 첫 줄에 삽입한다.
생성자, 초기화블럭 -> 상속 X
<에러가 나는 경우>
class Point{
int x,y;
Point(int x, int y){
this.x = x;
this.y = y;
}
}
class Point3D extends Point {
int z;
Point3D(int x, int y int z) {
this.x = x; //조상의 멤버 초기화 -> 에러
this.y = y; //조상의 멤버 초기화 -> 에러
this.z = z; //자손은 자신의 멤버만 초기화해야 한다.
}
}
<조상의 멤버 초기화 없이 조상의 생성자를 호출하는 법>
class Point{
int x,y;
Point(int x, int y){
this.x = x;
this.y = y;
}
}
class Point3D extends Point{
int z;
Point3D(int x, int y int z) {
super(x,y); // 조상 클래스의 생성자 Point(int x, int y)를 호출
this.z = z; //자신의 멤버를 초기화
}
}
추가조건
- 생성자의 첫 줄에 반드시 생성자를 호출해야 한다. 그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입한다.
class Point {
int x;
int y;
Point(){
this(0,0);
}
Point(int x, int y){
this.x=x;
this.y=y;
}
}
↓
class Point extends Object {
int x;
int y;
Point(){
this(0,0);
}
Point(int x, int y){
super(); // Object(); 조상 기본생성자 호출 코드를 컴파일러가 넣어줌
this.x=x;
this.y=y;
}
}
자식이 조상의 멤버를 초기화 하고 있기 때문에 에러가 나서 super(x, y)를 사용해서 생성자호출로 바꿔주어야 한다
'Java > 객체지향' 카테고리의 다른 글
[객체지향][자바의 정석] - 7.5 다형성 (0) | 2021.11.15 |
---|---|
[객체지향][자바의 정석] - 7.4 제어자 (0) | 2021.11.11 |
[객체지향][자바의 정석] - 7.1 상속(inheritance) (0) | 2021.11.04 |
자바의 정석 제 6장 정리 (0) | 2021.11.04 |
[객체지향][자바의 정석] - 5. 변수의 초기화 멤버변수의 초기화 (0) | 2021.11.02 |