JAVA/JAVA 기본정리

오버라이딩(overriding) / 오버로딩 (overloading) / super / super()

hyun-1200 2022. 5. 31. 19:22

오버라이딩 (overriding)

: 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것

  • 상속받은 메서드를 자손 클래스에 맞게 변경하는 경우, 조상의 메서드를 오버라이딩 한다. 
  • override : ~위에 덮어쓰다 (overwrite) 
class Point{
	int x;
    int y;
    String getLocation() { return "x :" + x + ", y" + y; }
}

class Point3D extends Point{
	int z;
    //오버라이딩 
    String getLocation() { return "x :" + x + ", y" + y + ", z" + z;  }
}

 

오버라이딩의 조건

자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와
1. 이름이 같아야 한다.
2. 매개변수가 같아야 한다.
3. 리턴값이 같아야 한다. 

 

다만, 접근제어자와 예외는 제한된 조건 하에서만 변경할 수 있다.

 

1. 접근제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다 (=같거나 넓은 범위로만 변경가능하다.) 

 

 * 접근제어자의 접근 범위 : public > protected > (default) > private 

  • 만일 조상 클래스에 정의된 메서드의 접근제어자가 protected라면, 이를 오버라이딩 하는 자손 클래스의 메서드는 접근제어자가 protected나 public 이여야 한다. 
  • 대부분의 경우 같은 범위의 접근제어자를 사용한다.

2. 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.

- 더 많은 개수의 예외를 선언할 수 없으며, 개수 뿐만 아니라 더 많은 범위의 예외도 선언할 수 없다. 

class Parent {
	void parentMethod() throws IOException, SQLException{ ... }
}

class Child extends Parent{
	void parentMethod() throws IOException { ... } //오류 
}

class Child extends Parent{
	void parentMethod() throws Exception { ... }  //오류
    // Exception은 모든 예외의 최고조상이므로 잘못된 오버라이딩이다. 
}

 

3. 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없다. 

- 조상 클래스에 정의된 static 메서드를 자손 클래스에서 똑같은 이름의 static 메서드로 정의 가능하다. 하지만 이것은 각 클래스에 별개의 static메서드를 정의한 것일 뿐 오버라이딩이 아니다. 각 메서드는 클래스이름으로 구별되며, 호출할 때는 '참조변수.메서드이름()' 대신 '클래스명.메서드이름()'으로 하는것이 바람직하다. 

- static멤버들은 자신들이 정의된 클래스에 묶여있다고 생각하라. 

 


오버로딩 ( overloading)  vs 오버라이딩 (overriding) 

오버로딩 ( overloading) : 기존에 없는 새로운 메서드를 정의하는 것 (new)
오버라이딩 ( overriding) : 상속받은 메서드의 내용을 변경하는 것 (change, modify) 

 

class Parent{
	void parentMethod(){}
}

class Child extends Parent{
	void parentMethod(){} // 오버라이딩
    void parentMethod(int x) {} //오버로딩 
    
    void childMethod(){}
    void childMethod(int x) {} //오버로딩
}

 

  • 오버라이딩 :  overwrite -> 덮어쓰다 -> change, modify
  • 오버로딩 : overloading -> 과적하다. 많이 싣다. -> new  
    • 오버로딩 : 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것 

 


super 

: 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수 

  • 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이 상속받은 멤버와 자신의 멤버이름이 같을 때 super로 구별한다.
  • 조상의 멤버와 자신의 멤버를 구별하는데 사용된다는 점을 제외하고는 super 대신 this는 근본적으로 같다.

 

this,  this() 정리했던 내용 다시 참고 : https://hyun-1200.tistory.com/39

 

생성자에서 다른 생성자 호출하기/ 참조변수 this와 생성자 this()

참조변수 this 인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어 있다.  생성자를 포함한 모든 인스턴스메서드에는 참조변수 'this'가 지역변수로 숨겨진 채로 존재한다. ex. long a,

hyun-1200.tistory.com

 

 

 

class Parent{
	int x= 10;
}
class Child extends Parent{
	int x= 20;
    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.x 는 조상클래스로부터 상속받은 멤버변수 x 이다.

- this.x는 자손클래스에 선언된 멤버변수이다.

 

- 메서드 역시 super을 이용해서 호출할 수 있다. 조상 클래스의 메서드를 자손클래스에서 오버라이딩한 경우에 super를 사용한다. 

 


super() 

: 조상 클래스의 생성자를 호출하는데 사용 / this()와 비슷 

 

  • 조상 클래스 멤버 초기화 작업이 수행되어야 하기 때문에 자손클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 한다.
  • super()도 this()와 같이 첫줄에서 생성자를 호출해야 하며, 그 이유는 자손클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있으므로 조상의 멤버들이 먼저 초기화되어 있어야 한다.
Object 클래스를 제외한 모든 클래스의 생성자 첫줄에 생성자, this() 또는 super()를 호출해야 한다. 그렇지 않으면 컴파일러가 자동적으로 super(); 를 생성자의 첫줄에 삽입한다. 

- 다만, 생성자가 정의되어 있는 클래스에는 컴파일러가 기본 생성자를 자동적으로 추가하지 않는다. 

 

 따라서, 조상 클래스의 멤버변수는 조상의 생성자에 의해 초기화되도록 해야 한다.

 

Point3D 생성자 첫 줄에 다른 생성자를 호출하지 않기 때문에 컴파일러가 super(); 를 여기에 삽입한다.

하지만, Point클래스의 기본생성자인 Point()는 정의되어있지 않기 때문에 컴파일 오류 발생한다.

 

따라서 아래와 같이 변경하면 문제없이 컴파일 된다.

조상 클래스의 멤버변수는 이처럼 조상의 생성자에 의해 초기화되도록 해야 하는 것이다.