logo

Java에서 재정의

하위 클래스가 상위 클래스에 이미 정의된 메서드에 대한 특정 구현을 제공하는 경우 이를 메서드 재정의라고 합니다. 하위 클래스의 재정의된 메서드에는 상위 클래스의 메서드와 동일한 이름 매개 변수 및 반환 유형이 있어야 합니다.

메서드 재정의 규칙

  • 이름 매개변수와 반환 유형은 상위 메소드와 일치해야 합니다.
  • Java는 참조 변수 유형뿐만 아니라 실제 객체 유형을 기반으로 런타임에 실행할 메소드를 선택합니다.
  • 정적 메서드는 재정의될 수 없습니다.
  • 그만큼 @Override 주석 메소드 이름의 오타와 같은 실수를 잡아냅니다.
Java
class Animal {    void move(){  System.out.println(  'Animal is moving.');     }  void eat(){    System.out.println(  'Animal is eating.');     } } class Dog extends Animal{    @Override void move(){     // move method from Base class is overriden in this  // method  System.out.println('Dog is running.');  }  void bark(){    System.out.println('Dog is barking.');     } } public class Geeks {  public static void main(String[] args)  {  Dog d = new Dog();  d.move();   d.eat();   d.bark();  } } 

산출
Dog is running. Animal is eating. Dog is barking. 

설명: Animal 클래스는 다음과 같은 기본 기능을 정의합니다. 이동하다() 그리고 먹다() . Dog 클래스는 Animal 및 재정의 특정 동작을 제공하는 move() 메서드 개가 달리고 있다. 두 클래스 모두 자체 메서드에 액세스할 수 있습니다. move()를 호출하는 Dog 객체를 생성할 때 재정의된 메서드가 실행됩니다.



Java의 메소드 재정의' title=

재정의의 특수 사례

1. super를 사용하여 부모 메서드 호출

그만큼 슈퍼 키워드 재정의 메서드에서 상위 클래스 메서드를 호출할 수 있습니다.

Java
class Parent{    void show(){    System.out.println('Parent's show()');  } } class Child extends Parent{    @Override  void show(){    super.show();  System.out.println('Child's show()');  } } public class Main{    public static void main(String[] args){    Parent obj = new Child();  obj.show();  } } 

산출
Parent's show() Child's show() 

2.  최종 메서드는 재정의될 수 없습니다.

메서드를 재정의하지 않으려면 다음과 같이 선언합니다.  결정적인 . 참조하세요  상속과 함께 Final 사용

인접각
Java
class Parent{    // Can't be overridden  final void show(){    } } class Child extends Parent{    // This would produce error  void show() {} } 


산출 :



메서드 재정의' loading='lazy' title=

3. 정적 방법

  • 정적 메서드는 재정의될 수 없습니다. 슈퍼클래스와 동일한 시그니처를 사용하여 하위 클래스에 정적 메서드를 정의하면 슈퍼클래스 메서드가 숨겨집니다.
  • 인스턴스 메서드는 재정의될 수 있지만 하위 클래스는 슈퍼클래스의 정적 메서드를 재정의할 수 없습니다.
  • 슈퍼클래스 정적 메서드와 동일한 시그니처를 가진 하위 클래스의 정적 메서드는 원래 메서드를 숨깁니다.
Java
class Parent{  static void staticMethod(){    System.out.println('Parent static method');  }  void instanceMethod(){    System.out.println('Parent instance method');  } } class Child extends Parent{    static void staticMethod(){    // Hides Parent's static method  System.out.println('Child static method');  }  @Override  void instanceMethod(){     // Overrides Parent's instance method  System.out.println('Child instance method');  } } public class GFG{    public static void main(String[] args){    Parent p = new Child();    // Calls Parent's static method (hiding)  p.staticMethod();    // Calls Child's overridden instance method  p.instanceMethod();   } } 

산출
Parent static method Child instance method 

4. 비공개 방법

  • 프라이빗 메서드는 하위 클래스에 표시되지 않으므로 재정의할 수 없습니다.
  • 동일한 이름을 가진 하위 클래스 메서드는 상위 클래스와 관련이 없는 새로운 독립 메서드로 처리됩니다.
Java
class Parent{    private void display(){    System.out.println('Parent private method');  } } class Child extends Parent{    void display(){    // This is a new method not overriding  System.out.println('Child method');  } } public class GFG{    public static void main(String[] args){    Child c = new Child();    // Calls Child's method  c.display();   } } 

산출
Child method 

5. 공변 반환 유형

  • 메서드 재정의에서 재정의 메서드의 반환 형식은 재정의된 메서드 반환 형식의 하위 클래스일 수 있습니다.
  • 이 기능은 공변 반환 유형으로 알려져 있으며 하위 클래스에서 보다 구체적인 반환 유형을 허용합니다.
Java
class Parent{    Parent getObject(){    System.out.println('Parent object');  return new Parent();  } } class Child extends Parent{    @Override    // Covariant return type  Child getObject() {   System.out.println('Child object');  return new Child();  } } public class GFG{    public static void main(String[] args){    Parent obj = new Child();    // Calls Child's method  obj.getObject();     } } 

산출
Child object 

재정의의 예외 처리

  • 재정의 메서드는 슈퍼클래스의 메서드보다 새롭거나 더 광범위한 확인된 예외를 발생시킬 수 없습니다.
  • 더 적거나 더 좁은 범위의 확인된 예외를 발생시킬 수 있습니다.
  • 슈퍼클래스 메서드에 관계없이 확인되지 않은 예외(예: RuntimeException)가 발생할 수 있습니다.
Java
import java.io.IOException; class Parent {  void display() throws IOException {  System.out.println('Parent method');  } } class Child extends Parent {  @Override  void display() throws IOException {  System.out.println('Child method');  } } public class GFG{    public static void main(String[] args){    // Parent reference Child object  Parent obj = new Child();   try{    // Calls Child's overridden method  obj.display();   } catch (IOException e){    System.out.println('Exception caught: ' + e.getMessage());  }  } } 

산출
Child method 

메소드 재정의를 사용하는 이유는 무엇입니까?

  • 하위 클래스에 있는 기존 메서드의 동작을 변경하거나 향상시키는 것입니다.
  • 런타임 다형성을 달성하기 위해 — 메소드 호출은 실제 객체 유형에 따라 달라집니다.
  • 메소드 이름을 재사용하여 논리적으로 중복성을 줄입니다.

실제 사례: 직원 관리 시스템

실제 비유를 통해 재정의를 이해해 보겠습니다.

조직의 직원 관리 시스템을 상상해 보세요. 모든 직원은 raiseSalary() 및 Promotion()과 같은 일부 동작을 공유하지만 관리자 또는 엔지니어와 같은 역할에 따라 논리가 다릅니다. 개별 직원이 다양한 유형(영업 기술 등)인 단일 Employee 배열을 만들고 해당 기능을 호출할 수 있습니다. 이렇게 하면 전체 코드가 많이 단순화됩니다.

Java
abstract class Employee {  abstract void raiseSalary();  abstract void promote(); } class Manager extends Employee{  @Override void raiseSalary(){    System.out.println(  'Manager salary raised with incentives.');  }  @Override void promote(){    System.out.println(  'Manager promoted to Senior Manager.');  } } class Engineer extends Employee{    @Override void raiseSalary(){    System.out.println(  'Engineer salary raised with bonus.');  }  @Override void promote(){    System.out.println(  'Engineer promoted to Senior Engineer.');  } } public class Company{    public static void main(String[] args){    Employee[] employees  = { new Manager() new Engineer() };  System.out.println('--- Raising Salaries ---');  for (Employee e : employees){    e.raiseSalary();   }  System.out.println('n--- Promotions ---');  for (Employee e : employees) {  e.promote();  }  } } 

산출
--- Raising Salaries --- Manager salary raised with incentives. Engineer salary raised with bonus. --- Promotions --- Manager promoted to Senior Manager. Engineer promoted to Senior Engineer. 

설명: Manager 및 Engineer 객체는 모두 Employee 유형을 사용하여 참조되지만 Java는 런타임 시 실제 객체의 재정의된 메소드를 호출하여 동적 메소드 디스패치(런타임 다형성)를 보여줍니다.



관련 기사: 메소드 오버로딩 및 메소드 오버라이딩