ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 메소드 재정의(Override)와 부모 메소드 호출(super)
    JAVA/클래스,상속,인터페이스,기본API 2024. 6. 5. 10:47

    ▤ 목차

       

      상속을 받아 사용하면서 자식 클래스에서 사용하기 적합하지 않을 수 있다.

      상속된 일부 메서드는 자식 클래스에서 다시 수정해서 사용해야 한다.

      이런 경우, 재정의 할 수 있는데 이를 메서드 오버라이드라고 한다.

      ✔ 오버라이드?

      상속된 메서드의 내용이 자식 클래스에 맞지 않을 경우, 자식 클래스에서 동일한 메서드를 재정의 하는 것을 말한다.

      편하게 말하자면 부모의 정의가 마음에 들지 않으면 자식 클래스에서 다시 정의하는 것이다.

      대신, 오버라이드를 하기 위해서는 규칙이 있다.

      아래 규칙으로 인해 오버라이딩이 되었다면 부모 객체의 메서드는 숨겨지기 때문에메서드를 호출하면 오버라이딩 된 자식의 메서드가 호출된다.

      ⌨ 규칙

      • 접근 제한을 더 강하게 정의할 수 없다.
      • 부모의 메서드와 같은 시그니처를 가져야 한다.
      • 새로운 예외(Exception)를 throws 할 수 없다.(예외는 나중에 자세히 정리하겠다.)
      시그니처란?
      리턴 타입, 메서드 이름, 매개 변수 리스트를 의미한다.

       

      접근 제한자
      약함 < -----------------------------------------------------> 강함
      public         default             protected                private

       

      💻 코드로 보기

      개과를 상속으로 표현해 보자.

      개라는 가장 큰 틀을 부모 클래스로공통부분을 묶어놓는다.

       

      Dog 클래스

      public class Dog {
      	//필드 멤버
      	private String name = "개";
      	
          //생성자
      	public Dog() {
      		// TODO Auto-generated constructor stub
      	}
      	
      	public Dog(String name) {
      		this.name = name;
      	}
      	
          //메소드(행위)
      	public String getName() {
      		return name;
      	}
      	public String callName() {
      		return "종류: "+name;
      	}
      	public void printMsg() {
      		System.out.println(name+": 지구에 산다");
      	}
      	
      }

       

       

      WolfDog 클래스

      public class WolfDog extends Dog{
      	private String where = "산";
      	
      	public WolfDog(String name) {
      		super(name);
      	}
      	
      	public void show() {
      		System.out.println("늑대가 사는 곳: " + where+"속");
      	}
      	
          //부모 클래스 재정의
      	@Override //어노테이션
      	public void printMsg() {
      		System.out.println(getName()+" ~ " + where + "에 산다.(요즘은 동물원)");
      	}
      	
          //울프독 고유 메서드
      	public void display() { 
      		printMsg(); //지역에서 먼저 찾은 후 멤버에서 찾는다.
      		this.printMsg(); //바로 멤버 메소드를 찾아간다.
      	}
      }

       

      `@Override`와 같은 모양을 어노테이션이라고 하는데, 이는 생략해도 상관이 없다.

      하지만 붙이면 컴파일러가 해당 어노테이션을 참고해 체크를 하기 때문에 개발자의 실수를 줄여준다.

       

      HouseDog 클래스

      public class HouseDog extends Dog{
      	private String where = "집";
      	
      	public HouseDog(String name) {
      		super(name);
      	}
      	
      	public void show() {
      		System.out.println("사는 곳: "+ where);
      	}
      	
      	@Override // 부모 메서드 재정의
      	public void printMsg() {
      		System.out.println(getName()+" - " + where + "에 산다.");
      	}
      }

       

      Main 메서드

       

      public class Main {
      
      	public static void main(String[] args) {
      		// 개과의 동물들 상속
      		Dog dog = new Dog();
      		dog.printMsg();
      		System.out.println(dog.callName());
      		
      		System.out.println("\n ==== houseDog에 대하여 ====");
      		HouseDog houseDog = new HouseDog("집 개");
      		houseDog.printMsg(); //재정의된 메소드 호출
      		System.out.println(houseDog.callName());
      		
      		System.out.println("\n ==== wolfDog에 대하여 ====");
      		WolfDog wolfdog = new WolfDog("늑대 개");
      		wolfdog.printMsg(); //재정의된 메소드 호출
      		System.out.println(wolfdog.callName());
      		wolfdog.display();
      		
      	}
      
      }

       

      결과

       

      👏 중요

      코드를 그냥 눈으로 훑어보는 것이 아니라 main메서드에서부터 코드의 흐름을 보면서 읽어야 한다.

      코드가 어떻게 돌아가는지 컴파일러가 되었다는 생각으로 코드의 흐름을 체크하면서 읽어보자!

       

      ✔ 부모 메서드(super) 호출하기

      자식 클래스에서 메서드를 오버라이딩하게 되면, 부모 메서드는 숨겨지고 오버라이딩된 메서드만 사용된다.

      자식 클래스 내부에서 오버라이딩된 부모 클래스의 메소드를 호출해야 하는 상황이 발생한다면?

      이런 경우 또한 종종 있는데, 명시적으로 super 키워드를 붙여서 부모 메서드를 호출하면 된다.

      super 키워드는 부모 객체를 참조하는 키워드이다. 때문에 부모 메서드에 직접 접근할 수 있다.

      ⌨ 형식

      super.부모메소드();

      💻 코드로 보기

      위의 예제를 활용해 보자.

       

      WolfDog 클래스

      public class WolfDog extends Dog{
      	private String where = "산";
      	
      	public WolfDog(String name) {
      		super(name);
      	}
      	
      	public void show() {
      		System.out.println("늑대가 사는 곳: " + where+"속");
      	}
      	
          //부모 클래스 재정의
      	@Override //어노테이션
      	public void printMsg() {
      		System.out.println(getName()+" ~ " + where + "에 산다.(요즘은 동물원)");
      	}
      	
          //울프독 고유 메서드
      	public void display() { 
      		printMsg(); //지역에서 먼저 찾은 후 멤버에서 찾는다.
      		this.printMsg(); //바로 멤버 메소드를 찾아간다.
              ///////////super. 추가 코드/////////////
              super.printMsg();
              //////////////////////////
      	}
      }

       

      가장 마지막 메서드인 display()를 보자. (눈에 띄라고 정렬을 안 했다ㅋㅋㅋ)

      위와 같이 super. 키워드를 사용하면 this. 키워드를 사용한 것과 달리, 부모의 메서드를 값을 찾아온다.

       

      😊정리

      많이 헷갈려하는 단어들이 많이 나왔지만, 의미나 사용이 전혀 다른 키워드들임을 확인하는 시간이었으면 좋겠다.

      정리를 하면서 개념이 더 확실하게 정리되는 기분이다.

      아는 것을 다시 보는 이유를 알 것 같다. 기본은 탄탄, 단단해야 한다.

      오버 로딩 VS 오버라이딩

      super() VS super.

      this() VS this.

      는 생긴 것만 비슷하지 쓰임은 다르다!

      무엇보다 상속은 뒤에 개념들과 계속 연쇄되어 헷갈릴 수 있는 개념이니 잘 정리하고 넘어갔으면 좋겠다.

    Designed by Tistory.