안녕! 이미 Java 메서드를 사용하고 있으며 이에 대해 많이 알고 있습니다.
이름은 같지만 인수 목록이 다른 여러 메서드가 있는 클래스를 본 적이 있을 것입니다. 그런 경우에 메서드 오버로딩을 사용했다는 것을 기억할 것입니다. 오늘은 다른 상황을 살펴보겠습니다. 하나의 공통 메서드가 있지만 호출되는 클래스에 따라 다른 작업을 수행해야 한다고 상상해 보십시오. 이 동작을 어떻게 구현합니까? 이를 이해하기 위해
. 말하는 방법을 많이 만들지 않으려고 합니다.
이름은 같지만 인수 목록이 다른 여러 메서드가 있는 클래스를 본 적이 있을 것입니다. 그런 경우에 메서드 오버로딩을 사용했다는 것을 기억할 것입니다. 오늘은 다른 상황을 살펴보겠습니다. 하나의 공통 메서드가 있지만 호출되는 클래스에 따라 다른 작업을 수행해야 한다고 상상해 보십시오. 이 동작을 어떻게 구현합니까? 이를 이해하기 위해
Animal동물을 나타내는 부모 클래스를 가져오고
speak그 안에 메서드를 만들어 봅시다.
public class Animal {
public void speak() {
System.out.println("Hello!");
}
}
이제 막 프로그램을 작성하기 시작했지만 아마도 잠재적인 문제를 볼 수 있을 것입니다. 세상은 많은 동물로 가득 차 있고 모두 다르게 "말합니다": 고양이 야옹, 오리 꽥꽥, 뱀 쉿쉿 소리 등. 우리의 목표는 간단합니다
. 말하는 방법을 많이 만들지 않으려고 합니다.
meow()야옹, 쉭쉭거리는 등의 메소드를 만드는 대신 메소드가 호출될
hiss()때 뱀이 쉭쉭대고 고양이가 야옹하고 개가 짖기를 원합니다 .
메서드 재정의
speak() 를 사용하여 쉽게 달성할 수 있습니다 . Wikipedia에서는 이 용어를 다음과 같이 설명합니다.
메서드 재정의
는 객체 지향 프로그래밍에서 하위 클래스 또는 하위 클래스가 상위 클래스 또는 상위 클래스 중 하나에서 이미 제공한 메서드의 특정 구현을 제공할 수 있도록 하는 언어 기능입니다. 기본적으로 맞습니다. 재정의를 사용하면 부모 클래스의 일부 메서드를 가져와 각 파생 클래스에서 고유한 구현을 작성할 수 있습니다. 하위 클래스의 새 구현은 상위 클래스의 구현을 "대체"합니다. 예를 들어 어떻게 보이는지 봅시다. 우리 클래스의 자손 4명을 만들어 봅시다
Animal.
public class Bear extends Animal {
@Override
public void speak() {
System.out.println("Growl!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void speak() {
System.out.println("Hiss!");
}
}
다음은 미래를 위한 작은 생활 꿀팁입니다. 상위 클래스의 메서드를 재정의하려면 IntelliJ IDE 에서 파생 클래스의 코드로 이동하고
Ctrl+O를 누르고 메뉴에서
메서드 재정의...를 선택합니다 . 처음부터 단축키 사용에 익숙해지십시오. 그들은 코딩 속도를 높일 것입니다! 원하는 동작을 얻기 위해 몇 가지 작업을 수행했습니다.
- 각 자손 클래스에서 부모 클래스의 메서드와 동일한 이름으로 메서드를 만들었습니다.
-
우리는 메서드에 부모 클래스와 동일한 이름을 부여하는 것이 아니라 그 동작을 재정의하고 싶다고 컴파일러에 알렸습니다. 컴파일러에 대한 이 "메시지"는 @Override 주석을 통해 전달됩니다.
메서드 위의 @Override 주석은 컴파일러(및 코드를 읽는 다른 프로그래머)에게 "걱정하지 마십시오. 이것은 실수나 실수가 아닙니다. 이 메서드가 이미 존재한다는 것을 알고 있으며 재정의하고 싶습니다. . - 우리는 각 자손 클래스에 필요한 구현을 작성했습니다. 메서드가 호출 되면
speak()뱀은 쉭쉭거리고 곰은 으르렁거립니다.
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Bear();
Animal animal4 = new Snake();
animal1.speak();
animal2.speak();
animal3.speak();
animal4.speak();
}
}
콘솔 출력:
Woof!
Meow!
Growl!
Hiss!
좋습니다. 모든 것이 제대로 작동합니다! 유형이 상위 클래스인 참조 변수 4개를 생성
Animal하고 하위 클래스의 서로 다른 개체 4개를 할당했습니다. 결과적으로 각 개체는 다르게 동작합니다. 각 파생 클래스에 대해 재정의된 메서드는 클래스 의
speak()기존 메서드를 대체합니다 (단순히 콘솔에 "Speaking: " 표시). 메서드 재정의에는 몇 가지 제한 사항이 있습니다.
speak()
Animal
-
재정의된 메서드는 부모 클래스의 메서드와 동일한 인수를 가져야 합니다.
speak부모 클래스의 메서드가 a를 입력으로 사용하는 경우String자손 클래스의 재정의된 메서드도 a를String입력으로 사용해야 합니다. 그렇지 않으면 컴파일러에서 오류가 발생합니다.public class Animal { public void speak(String s) { System.out.println("Speaking: " + s); } } public class Cat extends Animal { @Override // Error! public void speak() { System.out.println("Meow!"); } } -
재정의된 메서드는 부모 클래스의 메서드와 동일한 반환 형식을 가져야 합니다.
그렇지 않으면 컴파일 오류가 발생합니다.
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override public String speak() { // Error! System.out.println("Meow!"); return "Meow!"; } } -
재정의된 메서드의 액세스 한정자도 원본과 다를 수 없습니다.
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override private void speak() { // Error! System.out.println("Meow!"); } }
speak()클래스는 특정 동작 (개 짖는 소리, 고양이 울음 소리)을 갖지만 인터페이스는 단일 인터페이스입니다.
bark()
meow()
GO TO FULL VERSION