다형성 vs 재정의 vs 과부하


347

Java의 관점에서 누군가가 물을 때 :

다형성이란 무엇입니까?

겠습니까 과부하 또는 재정의 허용 해답이 될?

나는 그것보다 조금 더 있다고 생각합니다.

구현하지 않고 메소드를 정의한 추상 기본 클래스가 있고 서브 클래스에서 해당 메소드를 정의한 경우 여전히 대체입니까?

오버로드 가 정답이 아니라고 생각 합니다.


아래 답변은 다형성에 대해 잘 설명합니다. 그러나 나는 과부하가 일종의 다형성이라는 말에 강한 반대 의견을 가지고 있습니다. 내 질문에 대답하고 실제로 과부하에 집중하는 대답은 다형성인지 아닌지에 대한 것입니다. 이 스레드에 @The Digital Gabeg 답변이 있음을 정당화하려고했습니다. 정교화
PraveenKumar Lalasangi

답변:


894

다형성을 표현하는 가장 명확한 방법은 추상 기본 클래스 (또는 인터페이스)를 사용하는 것입니다.

public abstract class Human{
   ...
   public abstract void goPee();
}

이 클래스는 goPee()메소드가 인간에게 정의 할 수 없기 때문에 추상적 입니다. 서브 클래스 Male 및 Female에 대해서만 정의 할 수 있습니다. 또한 인간은 추상적 개념입니다. 남성도 여성도 아닌 인간을 만들 수는 없습니다. 둘 중 하나 여야합니다.

따라서 추상 클래스를 사용하여 구현을 연기합니다.

public class Male extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Stand Up");
    }
}

public class Female extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Sit Down");
    }
}

이제 인간으로 가득 찬 방 전체에 오줌을 줄 수 있습니다.

public static void main(String[] args){
    ArrayList<Human> group = new ArrayList<Human>();
    group.add(new Male());
    group.add(new Female());
    // ... add more...

    // tell the class to take a pee break
    for (Human person : group) person.goPee();
}

이것을 실행하면 다음을 얻을 수 있습니다.

Stand Up
Sit Down
...

37
@yuudachi. 수업을 가르 칠 때이 예를 생각해 냈습니다. 표준 "은행 계좌"클래스는 실제로 기본 클래스의 "추상성"을 표현하지 않았습니다. 다른 정식 예제 (동물, 소음 만들기)는 이해하기에는 너무 추상적입니다. 너무 명백한 서브 클래스가있는 단일베이스를 찾고있었습니다. 사실, goPee ()는 내가 성범이나 틀에 박힌 것이 아닌 유일한 예였습니다. (수업 시간에, 나는 "왼쪽의 복도"인쇄 대신 일어 서서 또는 앉아서 있지만.)
크리스 Cudmore을

100
이 예는 또한 계층 적 시스템을 사용하여 생물학적 시스템을 설명하기가 어렵다는 점을 강조합니다. 아주 어린 사람과 같은 일부 인간은 거의 모든 위치에서 오줌을 주며 아기는 goPee ()에게 쉽게 말할 수 없습니다. 어떤 인간은 성관계를 가지는데, 여기서 "남성"또는 "여성"의 생물학적 표지는 다소 정의되지 않습니다. 사회적 의미는 훨씬 더 복잡합니다. 교시의 예로서, 실금이거나 성관계가없는 누군가 (예 : OO 프로그래밍 학생)가 실제로 인간이 아니라는 의미와 같이 모델링 가정이 어떻게 부정적인 결과를 낳을 수 있는지 보여줍니다.
Andrew Dalke '

7
나는 여전히 당신의 코드에 맞지 않지만 "남성과 여성이 아닌 인간을 만들 수 없습니다"라는 논문을 반증 할 소수의 인간을 생각할 수 있습니다. ? ;)
Frank W. Zammetti

2
호출 할 goPee () 버전은 런타임에만 결정할 수 있기 때문에 다형성 일 뿐이라고 지적하는 것이 중요하다고 생각합니다. 이 예제는이를 암시하지만 이것이 왜 다형성인지 정확히 지적하는 것이 좋습니다. 또한 형제 클래스가 필요하지 않습니다. 부모-자식 관계 일 수도 있습니다. 또는 우연히 같은 기능을 가진 완전히 관련이없는 클래스. 이에 대한 예는 .toString () 함수일 수 있습니다. 어떤 객체에서든 무작위로 호출 할 수 있지만 컴파일러는 어떤 객체 유형을 정확하게 알 수 없습니다.
Tor Valamo

20
생물학적 복잡성에 대한 메모는 @AndrewDalke, +1입니다. 또한 goPee중력장을 입력으로 사용하지 않습니다. 전역 상태에 대한 이러한 의존성으로 인해 단위 테스트가 CatheterizedIntersexAstronaut어려워지고 서브 클래 싱이 특성의 구성을위한 최선의 방법은 아닐 수도 있습니다.
Mike Samuel

99

다형성 (polymorphism) 은 클래스 인스턴스가 마치 상속 트리에있는 다른 클래스의 인스턴스 인 것처럼 행동하는 능력입니다. 대부분의 경우 조상 클래스 중 하나입니다. 예를 들어 Java에서 모든 클래스는 Object에서 상속됩니다. 따라서 Object 유형의 변수를 작성하고 클래스의 인스턴스를 지정할 수 있습니다.

재정의다른 클래스에서 상속되는 클래스에서 발생하는 함수 유형입니다. 재정의 함수는 기본 클래스에서 상속 된 함수를 "대체"하지만 클래스의 인스턴스가 다형성을 통해 다른 유형 인 척하는 경우에도 호출되는 방식으로 호출됩니다. 이전 예제를 참조하면 자신의 클래스를 정의하고 toString () 함수를 재정의 할 수 있습니다. 이 함수는 Object에서 상속되므로이 클래스의 인스턴스를 Object-type 변수에 복사하면 계속 사용할 수 있습니다. 일반적으로 클래스가 Object 인 것처럼 클래스에서 toString ()을 호출하면 실제로 실행되는 toString 버전은 Object 자체에 정의 된 버전입니다. 그러나 함수가 재정의이므로 클래스 인스턴스의 toString () 정의는 클래스 인스턴스가

오버로드 는 이름은 같지만 매개 변수가 다른 여러 메소드를 정의하는 조치입니다. 재정의 또는 다형성과 관련이 없습니다.


8
이것은 오래되었지만 다형성이 다른 클래스가 상속 트리에 있어야 함을 의미하지는 않습니다. 인터페이스가 상속 트리의 일부로 간주되지만 인터페이스가 암시 적으로 구현되는 Go에서는 그렇지 않은 경우 Java에서 수행됩니다.
JN

5
실제로, 당신은 다형성을위한 클래스가 전혀 필요하지 않습니다.
StCredZero

3
나는 초보자이며, 틀렸다면 나를 고치지 만 과부하가 다형성과 관련이 없다고 말하지는 않을 것입니다. 적어도 Java에서 다형성은 호출자의 유형을 기반으로 구현을 선택할 때이며 오버로드는 매개 변수 유형을 기반으로 구현을 선택할 때입니다. 둘 사이의 유사점을 보면 이해하는 데 도움이됩니다.
csjacobs24

9
잘못되었습니다. Ad hoc polymorphism당신이 당신의 설명 무엇 오버로딩의 섹션 입니다 다형성의 경우.
Jossie Calderon

1
"이는 재정의 또는 다형성과 관련이 없습니다." 이 진술은 잘못되었습니다.
Shailesh Pratapwar

45

다형성이란 요구 사항에 따라 다른 작업을 수행하는 하나 이상의 동일한 형태를 의미합니다.

다형성은 두 가지 방법으로 달성 할 수 있습니다.

  1. 메서드 재정의
  2. 메소드 오버로딩

메소드 오버로드 는 동일한 메소드 이름을 사용하여 동일한 클래스에 둘 이상의 메소드를 작성하는 것을 의미하지만 전달 매개 변수는 다릅니다.

메서드 재정의 는 다른 클래스에서 메서드 이름을 사용한다는 것을 의미합니다. 즉, 부모 클래스 메서드는 자식 클래스에서 사용됩니다.

Java에서 다형성을 달성하기 위해 수퍼 클래스 참조 변수는 서브 클래스 오브젝트를 보유 할 수 있습니다.

다형성을 달성하려면 모든 개발자가 프로젝트에서 동일한 메소드 이름을 사용해야합니다.


4
좋은 답변을 얻으려면 +1하십시오. 허용되는 답변은 한 가지 유형의 다형성 만 설명합니다. 이 답변은 완료되었습니다.
apadana

1
다형성은 패러다임 (OOP)이지만 오버라이드 및 오버로딩은 언어 기능입니다.
曾 其 威

다형성은 또한 일반적인 유형에 의해 달성 될 수있다.
Minh Nghĩa

43

pseudo-C # / Java에서 다형성의 예는 다음과 같습니다.

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

Main 함수는 동물의 유형을 모르고 MakeNoise () 메서드의 특정 구현 동작에 따라 다릅니다.

편집 : 브라이언이 나를 때리는 펀치처럼 보입니다. 우린 같은 예를 사용했습니다. 그러나 위의 코드는 개념을 명확히하는 데 도움이됩니다.


런타임 다형성의 예입니다. 컴파일 타임 다형성은 메소드 오버로딩과 제네릭 형식을 통해 가능합니다.
피트 Kirkham

모양-> 평행 사변형-> 사각형-> 사각형
mpen

이 경우 @ yankee2905, 클래스가 여러 인터페이스를 구현할 수 있으므로 인터페이스를 사용할 수 있다고 생각합니다.
Sam003

1
@Zhisheng 또는 추상 부모 클래스에 오줌 메소드를 추가합니까? 인터페이스를 사용하여 다른 것을 구현합니다.
joey rohan

43

재정의와 과부하 모두 다형성을 달성하는 데 사용됩니다.

하나 이상의 서브 클래스에서 재정의 되는 클래스에 메소드가있을 수 있습니다 . 이 메소드는 객체를 인스턴스화하는 데 사용 된 클래스에 따라 다른 작업을 수행합니다.

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

    class Coffee extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature > 70;
       }
    }

    class Wine extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature < 10;
       }
    }

또한 둘 이상의 인수 세트로 오버로드 되는 메소드가있을 수 있습니다 . 이 메소드는 전달 된 인수의 유형에 따라 다른 작업을 수행합니다.

    class Server {
        public void pour (Coffee liquid) {
            new Cup().fillToTopWith(liquid);
        }

        public void pour (Wine liquid) {
            new WineGlass().fillHalfwayWith(liquid);
        }

        public void pour (Lemonade liquid, boolean ice) {
            Glass glass = new Glass();
            if (ice) {
                glass.fillToTopWith(new Ice());
            }
            glass.fillToTopWith(liquid);
        }
    }

역사적으로 메서드 오버로드가 객체 지향 패러다임의 다형성의 일부로 간주되지 않기 때문에 투표가 거부되었다고 생각합니다. 메소드 오버로딩과 다형성은 프로그래밍 언어의 두 가지 직교 독립적 기능입니다.
Sergio Acosta

7
여기에 내 대답에서 언급했듯이 두 가지 기능이 직교는 아니지만 밀접한 관련이 있습니다. 다형성! = 상속. 당신은 내 투표를했습니다.
Peter Meyer

2
즉, 다형성 대 임시 다형성을 입력하십시오. 오버로드와 오버라이드가 모두 다형성과 관련되어 있다고 올바르게 설명되어 있기 때문에 완벽하지는 않지만이 답변을지지하고 있습니다. OOP 언어의 다형성은 클래스 상속에 의해서만 달성 될 수 있다고 말하는 것은 단순히 잘못입니다. 우리는 Java 및 C ++ 외에도 다중 디스패치, 임시 다형성, 파라 메트릭 다형성 등과 같은 개념을 사용할 수있는 다른 OOP 언어가 있다는 것을 기억해야합니다 .
rsenna

2
@rsenna 이것은 불완전 할 수 있지만 나머지 IMHO보다 훨씬 나은 질문에 대답합니다. 또한 ad-hoc 및 parametric polymorphism을 언급 한 것이 좋습니다.
Valentin Radu 2016 년

15

과부하가 답이 아닌 것이 맞습니다.

어느 것도 무시하지 않습니다. 재정의는 다형성을 얻는 수단입니다. 다형성은 객체가 유형에 따라 동작을 변화시키는 능력입니다. 다형성을 나타내는 객체의 호출자가 객체의 특정 유형을 알지 못하는 경우에 가장 잘 설명됩니다.


3
변화하는 객체의 행동이 아니라 그의 구현이어야합니다. 같은 행동, 다른 구현, 다형성입니다.
QBziZ

@QBziZ 당신은 정의해야 할 행동 , 특히 형용사 같은 . 동작이 동일하다면 왜 구현이 달라야합니까? 누군가 특정 구현에 만족하지 않기 때문에 다른 구현이 필요합니다.
Sнаđошƒаӽ

11

특히 오버로드 또는 오버라이드는 전체 그림을 제공하지 않습니다. 다형성은 단순히 객체의 유형에 따라 동작을 특수화하는 능력입니다.

오버로드는 같은 이름의 메소드가 다르게 매개 변수 유형을 지정할 수있는 경우 다형성 (매개 변수 다형성)의 형태라는 점에서 일부 답변에 동의하지 않습니다. 좋은 예는 연산자 오버로드입니다. 문자열 또는 int와 같은 다른 유형의 매개 변수를 허용하도록 "+"를 정의 할 수 있으며 이러한 유형에 따라 "+"는 다르게 동작합니다.

다형성에는 상속 및 재정의 방법도 포함되지만 기본 유형에서는 추상적이거나 가상 일 수 있습니다. 상속 기반 다형성 측면에서 Java는 단일 클래스 상속 만 지원하여 단일 유형의 기본 유형 체인의 다형성 동작으로 제한합니다. Java는 또 다른 형태의 다형성 동작 인 다중 인터페이스의 구현을 지원합니다.


관련된 단어가 일반적으로 무엇을 의미하는지에 대해서는 맞습니다. 그러나 프로그래밍 컨텍스트에서 사람들이 "다형성"이라고 할 때는 항상 "상속 기반 다형성"을 의미합니다. 흥미로운 점이지만, 이런 방식으로 다형성을 기술하면 사람들을 혼란스럽게 할 것이라고 생각합니다.
Digital Gabeg

상속만으로도 다형성을 설명하는 것이 더 쉬울 수 있지만,이 특정한 질문이 제기 된 방식은 파라 메트릭 다형성을 설명하는 것이 현명하다고 생각합니다.
Patrick McElhaney

4
분명히, 나는 여기에 절대적으로 제시되는 몇 가지 답변이 있기 때문에 다른 양식을 언급해야한다고 생각합니다. "프로그래머 문맥에서 '다형성'은 항상 '상속 기반 다형성'을 의미한다"
Peter Meyer

2
오버로드가 Ad-hoc_polymorphism en.wikipedia.org/wiki/
Manu

나는 'The Digital Gabeg'에 동의하는 경향이 있습니다. OOP에 대해 논의하고 있다면 다형성은 일반적으로 하위 유형 다형성을 의미하며, 유형 이론에 대해 논의하는 경우 모든 유형의 다형성을 의미하지만 '프로그래머 컨텍스트'를 사용하면 너무 모호합니다.
Manu

7

다형성은 단순히 "많은 형태"를 의미합니다.

상속이 아닌 인터페이스 구현으로 다목적 요구를 충족시키기 때문에 상속을 요구하지 않습니다. 논란의 여지가 있지만 인터페이스 구현은 상속보다 "더 나은"다형성 요구를 충족시킵니다.

예를 들어, 날 수있는 모든 것을 설명하는 수퍼 클래스를 만드시겠습니까? 나는 생각하지 않아야한다. 비행을 설명하는 인터페이스를 작성하고 그대로 두는 것이 가장 좋습니다.

따라서 인터페이스는 동작을 설명하고 메서드 이름은 동작을 (프로그래머에게) 설명하므로 메서드 오버로드를 더 적은 형태의 다형성으로 간주하기에는 무리가 없습니다.


2
정답은 아직 최고입니다. 다형성은 명사 (클래스) 또는 동사 (방법)와 같은 모든 언어 구성에 적용될 수 있습니다.
Radu Gasler

6

고전적인 예, 개와 고양이는 동물이며, 동물은 makeNoise 방법을 가지고 있습니다. makeNoise라고 부르는 일련의 동물을 반복하고 각각의 구현을 할 것으로 기대합니다.

호출 코드는 그들이 어떤 특정 동물인지 알 필요가 없습니다.

그것이 내가 다형성이라고 생각하는 것입니다.


4

다형성은 객체가 여러 형태로 나타날 수있는 기능입니다. 여기에는 상속 및 가상 함수를 사용하여 상호 교환 할 수있는 개체군을 구축하는 것이 포함됩니다. 기본 클래스에는 응용 프로그램이 지시 한대로 구현되지 않았거나 기본 구현으로 구현 된 가상 함수의 프로토 타입이 포함되어 있으며 다양한 파생 클래스는 각각 다른 동작에 영향을주기 위해 다르게 구현합니다.


4

둘 다 :

오버로드는 다른 매개 변수를 사용하는 동일한 기능 이름을 갖는 경우입니다.

재정의는 자식 클래스가 부모의 메서드를 자체 메서드 중 하나로 대체 할 때입니다 (자체적으로 다형성을 구성하지 않음).

다형성은 늦은 바인딩입니다. 예를 들어 기본 클래스 (부모) 메서드가 호출되고 있지만 런타임에 응용 프로그램에서 실제 개체가 무엇인지 알 때까지는 그렇지 않습니다. 메서드가 다른 자식 클래스 일 수 있습니다. 기본 클래스가 정의 된 모든 하위 클래스를 사용할 수 있기 때문입니다.

Java에서는 콜렉션 라이브러리에서 다형성을 많이 볼 수 있습니다.

int countStuff(List stuff) {
  return stuff.size();
}

List는 기본 클래스이며, List처럼 작동하는 한 연결된 목록, 벡터, 배열 또는 사용자 정의 목록 구현을 계산하는 경우 컴파일러는 실마리가 없습니다.

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

과부하가 발생하면 다음을 수행하십시오.

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

그리고 올바른 버전의 countStuff ()가 매개 변수와 일치하도록 컴파일러에서 선택됩니다.


4

다형성에 대해서는 이미이 글에서 자세하게 설명하고 있지만 그 이유에 대해 더 강조하고 싶습니다.

모든 OOP 언어에서 다형성이 중요한 이유

상속 / 다형성이 있거나없는 TV를위한 간단한 응용 프로그램을 만들어 봅시다. 응용 프로그램의 각 버전을 게시하면 소급 적용됩니다.

TV 회사의 소프트웨어 엔지니어이고 볼륨, 밝기 및 색상 컨트롤러 용 소프트웨어를 작성하여 사용자 명령에서 값을 늘리거나 줄이라고 가정합니다.

다음을 추가하여 이러한 각 기능에 대한 클래스 작성으로 시작하십시오.

  1. set :-컨트롤러의 값을 설정합니다. (이것은 컨트롤러 특정 코드가 있다고 가정)
  2. get :-컨트롤러의 값을 얻으려면 (이것은 컨트롤러 특정 코드가 있다고 가정).
  3. adjust :-입력을 확인하고 컨트롤러를 설정합니다. (일반적인 유효성 검사 .. 컨트롤러와 무관)
  4. 컨트롤러를 통한 사용자 입력 매핑 :-사용자 입력을 얻고 컨트롤러를 적절하게 호출합니다.

응용 프로그램 버전 1

import java.util.Scanner;    
class VolumeControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV1    {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

/*
 *       There can be n number of controllers
 * */
public class TvApplicationV1 {
    public static void main(String[] args)  {
        VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
        BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
        ColourControllerV1 colourControllerV1 = new ColourControllerV1();


        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println("Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV1.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV1.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV1.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV1.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV1.adjust(5);
                    break;
                }
                case 6: {
                colourControllerV1.adjust(-5);
                break;
            }
            default:
                System.out.println("Shutting down...........");
                break OUTER;
        }

    }
    }
}

이제 첫 번째 버전의 작업 응용 프로그램을 배포 할 준비가되었습니다. 지금까지 수행 한 작업을 분석 할 시간입니다.

TV 응용 프로그램 버전 1의 문제

  1. Adjust (int value) 코드는 세 클래스 모두에서 중복됩니다. 코드 이중성을 최소화하고 싶습니다. (그러나 중복 코드를 피하기 위해 공통 코드를 생각하지 않고 슈퍼 클래스로 옮기지 않았습니다)

응용 프로그램이 예상대로 작동하는 한 계속 사용하기로 결정했습니다.

때때로, 당신의 보스가 당신에게 돌아와서 기존 응용 프로그램에 재설정 기능을 추가하도록 요청합니다. Reset은 3 개의 3 개의 컨트롤러를 각각의 기본값으로 설정합니다.

새 기능에 대한 새 클래스 (ResetFunctionV2)를 작성하기 시작하고이 새 기능에 대한 사용자 입력 맵핑 코드를 맵핑하십시오.

응용 프로그램 버전 2

import java.util.Scanner;
class VolumeControllerV2    {

    private int defaultValue = 25;
    private int value;

    int getDefaultValue() {
        return defaultValue;
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV2   {

    private int defaultValue = 50;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV2    {

    private int defaultValue = 40;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class ResetFunctionV2 {

    private VolumeControllerV2 volumeControllerV2 ;
    private BrightnessControllerV2 brightnessControllerV2;
    private ColourControllerV2 colourControllerV2;

    ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2)  {
        this.volumeControllerV2 = volumeControllerV2;
        this.brightnessControllerV2 = brightnessControllerV2;
        this.colourControllerV2 = colourControllerV2;
    }
    void onReset()    {
        volumeControllerV2.set(volumeControllerV2.getDefaultValue());
        brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
        colourControllerV2.set(colourControllerV2.getDefaultValue());
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV2 {
    public static void main(String[] args)  {
        VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
        BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
        ColourControllerV2 colourControllerV2 = new ColourControllerV2();

        ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV2.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV2.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV2.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV2.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV2.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV2.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV2.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

따라서 재설정 기능으로 응용 프로그램을 준비했습니다. 그러나 지금 당신은 그것을 깨닫기 시작합니다

TV 응용 프로그램 버전 2의 문제

  1. 새 컨트롤러가 제품에 도입 된 경우 재설정 기능 코드를 변경해야합니다.
  2. 컨트롤러 수가 너무 많으면 컨트롤러 참조를 보유하는 데 문제가있을 수 있습니다.
  3. 리셋 기능 코드는 모든 컨트롤러 클래스 코드와 밀접하게 연결되어 있습니다 (기본값을 가져오고 설정합니다).
  4. 기능 클래스 재설정 (ResetFunctionV2)은 바람직하지 않은 Controller 클래스의 다른 방법 (조정)에 액세스 할 수 있습니다.

동시에, 보스로부터 귀하는 각 컨트롤러가 시작시 인터넷을 통해 회사의 호스트 드라이버 저장소에서 최신 버전의 드라이버를 확인해야하는 기능을 추가해야 할 수도 있다고 들었습니다.

이제 추가 할이 새로운 기능이 재설정 기능과 유사하며 응용 프로그램을 리팩터링하지 않으면 V2 (응용 프로그램 문제)가 곱해질 것이라고 생각하기 시작합니다.

JAVA의 다형성 (polymorphic) 기능을 활용할 수 있도록 상속 사용을 고려하고 새로운 추상 클래스 (ControllerV3)를 추가합니다.

  1. get 및 set 메소드의 서명을 선언하십시오.
  2. 모든 컨트롤러에서 이전에 복제 된 adjust 메소드 구현을 포함합니다.
  3. 다형성을 활용하여 재설정 기능을 쉽게 구현할 수 있도록 setDefault 메소드를 선언하십시오.

이러한 개선 사항을 통해 TV 응용 프로그램 버전 3을 사용할 수 있습니다.

응용 프로그램 버전 3

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

abstract class ControllerV3 {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
    abstract void setDefault();
}
class VolumeControllerV3 extends ControllerV3   {

    private int defaultValue = 25;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
}
class  BrightnessControllerV3  extends ControllerV3   {

    private int defaultValue = 50;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
}
class ColourControllerV3 extends ControllerV3   {

    private int defaultValue = 40;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
}

class ResetFunctionV3 {

    private List<ControllerV3> controllers = null;

    ResetFunctionV3(List<ControllerV3> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (ControllerV3 controllerV3 :this.controllers)  {
            controllerV3.setDefault();
        }
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV3 {
    public static void main(String[] args)  {
        VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
        BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
        ColourControllerV3 colourControllerV3 = new ColourControllerV3();

        List<ControllerV3> controllerV3s = new ArrayList<>();
        controllerV3s.add(volumeControllerV3);
        controllerV3s.add(brightnessControllerV3);
        controllerV3s.add(colourControllerV3);

        ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV3.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV3.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV3.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV3.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV3.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV3.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV3.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

V2의 문제 목록에 나열된 대부분의 문제가 해결되었지만

TV 응용 프로그램 버전 3의 문제

  1. 기능 클래스 재설정 (ResetFunctionV3)은 ​​바람직하지 않은 Controller 클래스의 다른 방법 (조정)에 액세스 할 수 있습니다.

다시 말하지만, 구현할 다른 기능 (시작시 드라이버 업데이트)이 있으므로이 문제를 해결하려고합니다. 수정하지 않으면 새로운 기능으로 복제됩니다.

따라서 추상 클래스에 정의 된 계약을 나누고 두 가지 인터페이스를 작성하십시오.

  1. 기능을 재설정하십시오.
  2. 드라이버 업데이트.

그리고 첫 번째 구체적인 수업에 아래와 같이 구현하십시오.

응용 프로그램 버전 4

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

interface OnReset {
    void setDefault();
}
interface OnStart {
    void checkForDriverUpdate();
}
abstract class ControllerV4 implements OnReset,OnStart {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class VolumeControllerV4 extends ControllerV4 {

    private int defaultValue = 25;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for VolumeController .... Done");
    }
}
class  BrightnessControllerV4 extends ControllerV4 {

    private int defaultValue = 50;
    private int value;
    @Override
    int get()    {
        return value;
    }
    @Override
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }

    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for BrightnessController .... Done");
    }
}
class ColourControllerV4 extends ControllerV4 {

    private int defaultValue = 40;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for ColourController .... Done");
    }
}
class ResetFunctionV4 {

    private List<OnReset> controllers = null;

    ResetFunctionV4(List<OnReset> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (OnReset onreset :this.controllers)  {
            onreset.setDefault();
        }
    }
}
class InitializeDeviceV4 {

    private List<OnStart> controllers = null;

    InitializeDeviceV4(List<OnStart> controllers)  {
        this.controllers = controllers;
    }
    void initialize()    {
        for (OnStart onStart :this.controllers)  {
            onStart.checkForDriverUpdate();
        }
    }
}
/*
*       so on
*       There can be n number of controllers
*
* */
public class TvApplicationV4 {
    public static void main(String[] args)  {
        VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
        BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
        ColourControllerV4 colourControllerV4 = new ColourControllerV4();
        List<ControllerV4> controllerV4s = new ArrayList<>();
        controllerV4s.add(brightnessControllerV4);
        controllerV4s.add(volumeControllerV4);
        controllerV4s.add(colourControllerV4);

        List<OnStart> controllersToInitialize = new ArrayList<>();
        controllersToInitialize.addAll(controllerV4s);
        InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
        initializeDeviceV4.initialize();

        List<OnReset> controllersToReset = new ArrayList<>();
        controllersToReset.addAll(controllerV4s);
        ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV4.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV4.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV4.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV4.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV4.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV4.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV4.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

이제 당신이 직면 한 모든 문제가 해결되었으며 상속과 다형성을 사용하면

  1. 응용 프로그램의 다양한 부분을 느슨하게 연결하십시오. (재설정 또는 드라이버 업데이트 기능 구성 요소는 실제 컨트롤러 클래스 (볼륨, 밝기 및 색상)를 알 필요가 없으며 OnReset 또는 OnStart를 구현하는 모든 클래스는 재설정 또는 드라이버 업데이트 기능을 사용할 수 있습니다 구성 요소).
  2. 응용 프로그램 향상이 쉬워집니다 (컨트롤러의 새로운 추가는 재설정 또는 드라이버 업데이트 기능 구성 요소에 영향을 미치지 않으며 이제 새로운 구성 요소를 추가하는 것이 매우 쉽습니다)
  3. 추상화 계층 유지 (이제 재설정 기능은 컨트롤러의 setDefault 메소드 만 볼 수 있고 재설정 기능은 컨트롤러의 checkForDriverUpdate 메소드 만 볼 수 있음)

도움이 되었기를 바랍니다 :-)


3

오버로딩이라는 용어는 같은 이름을 가진 여러 버전의 무언가를 가지며 일반적으로 매개 변수 목록이 다른 메소드를 말합니다

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

따라서 이러한 함수는 동일한 기능을 수행 할 수 있지만 ID 또는 이름으로 호출 할 수 있습니다. 상속, 추상 클래스 등과는 아무런 관련이 없습니다.

재정의는 일반적으로 질문에 설명 된대로 다형성을 나타냅니다.


2

오버로드는 이름은 같지만 매개 변수가 다른 두 개의 메소드를 정의 할 때입니다.

재정의는 하위 클래스에서 이름이 같은 함수를 통해 기본 클래스의 동작을 변경하는 곳입니다.

따라서 다형성은 재정의와 관련이 있지만 실제로 과부하는 아닙니다.

그러나 누군가 "다형성이란 무엇입니까?"라는 질문에 대해 "재정의"에 대한 간단한 대답을한다면 자세한 설명을 부탁드립니다.


2

재정의는 상위 수준 메서드 (슈퍼 메서드)와 이름과 서명이 같은 메서드를 선언하여 상속 된 메서드를 숨기는 것과 비슷합니다. 이렇게하면 클래스에 다형성 동작이 추가됩니다. 다시 말해서 호출 할이트 레벨 메소드를 선택하기로 한 결정은 컴파일 타임이 아닌 런타임에 이루어집니다. 이것은 인터페이스와 구현의 개념으로 이어진다.


2

다형성이란 무엇입니까?

자바 튜토리얼에서

다형성의 사전 정의는 유기체 또는 종이 다양한 형태 또는 단계를 가질 수있는 생물학의 원리를 말합니다. 이 원칙은 객체 지향 프로그래밍 및 Java 언어와 같은 언어에도 적용될 수 있습니다. 클래스의 서브 클래스는 고유 한 동작을 정의 할 수 있지만 부모 클래스와 동일한 기능을 공유 할 수 있습니다.

예제와 정의를 고려하여 재정의 를 받아 들여야합니다.

두 번째 쿼리와 관련하여 :

구현하지 않고 메소드를 정의한 추상 기본 클래스가 있고 서브 클래스에서 해당 메소드를 정의한 경우 여전히 대체입니까?

재정의라고합니다.

다른 유형의 재정의를 이해하려면이 예제를 살펴보십시오.

  1. 기본 클래스는 구현을 제공하지 않으며 하위 클래스는 전체 메소드를 대체해야합니다.-(추상)
  2. 기본 클래스는 기본 구현을 제공하고 하위 클래스는 동작을 변경할 수 있습니다
  3. 하위 클래스는 호출하여 기본 클래스 구현에 확장을 추가합니다 super.methodName() 첫 번째 문 합니다
  4. 기본 클래스는 알고리즘의 구조를 정의하고 (템플릿 방법) 하위 클래스는 알고리즘의 일부를 재정의합니다.

코드 스 니펫 :

import java.util.HashMap;

abstract class Game implements Runnable{

    protected boolean runGame = true;
    protected Player player1 = null;
    protected Player player2 = null;
    protected Player currentPlayer = null;

    public Game(){
        player1 = new Player("Player 1");
        player2 = new Player("Player 2");
        currentPlayer = player1;
        initializeGame();
    }

    /* Type 1: Let subclass define own implementation. Base class defines abstract method to force
        sub-classes to define implementation    
    */

    protected abstract void initializeGame();

    /* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
    protected void logTimeBetweenMoves(Player player){
        System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
    }

    /* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
        super.methodName() in first line of the child class method and specific implementation later */
    protected void logGameStatistics(){
        System.out.println("Base class: logGameStatistics:");
    }
    /* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
    protected void runGame() throws Exception{
        System.out.println("Base class: Defining the flow for Game:");  
        while ( runGame) {
            /*
            1. Set current player
            2. Get Player Move
            */
            validatePlayerMove(currentPlayer);  
            logTimeBetweenMoves(currentPlayer);
            Thread.sleep(500);
            setNextPlayer();
        }
        logGameStatistics();
    }
    /* sub-part of the template method, which define child class behaviour */
    protected abstract void validatePlayerMove(Player p);

    protected void setRunGame(boolean status){
        this.runGame = status;
    }
    public void setCurrentPlayer(Player p){
        this.currentPlayer = p;
    }
    public void setNextPlayer(){
        if ( currentPlayer == player1) {
            currentPlayer = player2;
        }else{
            currentPlayer = player1;
        }
    }
    public void run(){
        try{
            runGame();
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

class Player{
    String name;
    Player(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}

/* Concrete Game implementation  */
class Chess extends Game{
    public Chess(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized Chess game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate Chess move:"+p.getName());
    }
    protected void logGameStatistics(){
        super.logGameStatistics();
        System.out.println("Child class: Add Chess specific logGameStatistics:");
    }
}
class TicTacToe extends Game{
    public TicTacToe(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized TicTacToe game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate TicTacToe move:"+p.getName());
    }
}

public class Polymorphism{
    public static void main(String args[]){
        try{

            Game game = new Chess();
            Thread t1 = new Thread(game);
            t1.start();
            Thread.sleep(1000);
            game.setRunGame(false);
            Thread.sleep(1000);

            game = new TicTacToe();
            Thread t2 = new Thread(game);
            t2.start();
            Thread.sleep(1000);
            game.setRunGame(false);

        }catch(Exception err){
            err.printStackTrace();
        }       
    }
}

산출:

Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:

2

나는 너희들이 개념을 섞고 있다고 생각한다. 다형성 은 객체가 런타임에 다르게 동작하는 능력입니다. 이를 위해서는 두 가지 필수 조건이 필요합니다.

  1. 늦은 바인딩
  2. 계승.

말해 두 겠는데 그 과부하 수단을에 다른 것을 무시 당신이 사용하는 언어에 따라. 예를 들어 Java에서는 재정의가 아니라 과부하 가 존재합니다 . 서브 클래스에서 기본 클래스와 다른 서명을 가진 오버로드 된 메소드를 사용할 수 있습니다. 그렇지 않으면 그것들이 무시 될 것입니다 (제발, 객체 외부에서 기본 클래스 메소드를 호출 할 수있는 방법이 없다는 것을 의미합니다).

그러나 C ++에서는 그렇지 않습니다. 상관 과부하 에있어서, 상기 서명이 아니라 동일한 여부 (diffrrent 양은 다른 타입) 독립적 여부 재정의가 . 즉, 기본 클래스의 메소드는 서브 클래스 객체 외부에서 호출 될 때 더 이상 서브 클래스에서 더 이상 사용할 수 없습니다.

따라서 Java 사용 오버로딩 에 대해 이야기 할 때 답이됩니다 . 다른 언어에서는 C ++에서와 같이 다를 수 있습니다.


1

다형성은 그것이 의미하는 한 더 가능성이 높습니다 가 관련 ... Java에서 덮어 쓰기

각기 다른 상황에서 SAME 객체의 다른 행동에 관한 것입니다 (프로그래밍 방식에서 ... 다른 인수를 호출 할 수 있습니다)

아래 예제는 이해하는 데 도움이 될 것이라고 생각합니다 ... PURE Java 코드는 아니지만 ...

     public void See(Friend)
     {
        System.out.println("Talk");
     }

그러나 우리가 인수를 바꾸면 ... 행동이 바뀔 것입니다 ...

     public void See(Enemy)
     {
        System.out.println("Run");
     }

Person (여기서는 "Object")은 동일합니다 ...


1

다형성은 객체의 여러 구현이거나 여러 형태의 객체를 말할 수 있습니다. 클래스 Animals를 추상 기본 클래스로 사용하고 movement()동물이 움직이는 방식을 정의 하는 메소드 가 있습니다. 실제로 우리는 서로 다른 종류의 동물을 가지고 있으며 그것들은 다르게 움직입니다. 그들 중 일부는 2 개의 다리로, 다른 것은 4 개, 그리고 다리가없는 일부 등입니다. movement()지구상의 각 동물마다 다른 것을 정의하려면 다형성을 적용해야합니다. 그러나 더 많은 클래스, 즉 클래스 Dogs Cats Fish등 을 정의해야합니다 . 그런 다음 기본 클래스에서 해당 클래스를 확장 Animals하고 해당 메소드를 대체해야합니다.movement() 가지고있는 각 동물을 기반으로하는 새로운 이동 기능으로 를 해야합니다. 당신은 또한 사용할 수 있습니다Interfaces그것을 달성하기 위해. 여기의 키워드는 재정의 중이며, 과부하가 다를 수 있으며 다형성으로 간주되지 않습니다. 오버로딩을 사용하면 "같은 이름으로"여러 객체를 정의 할 수 있지만 동일한 객체 나 클래스에서 다른 매개 변수를 사용하면됩니다.


0

다형성은 단일 인터페이스를 사용하여 언어가 다른 객체를 균일하게 처리하는 능력과 관련이 있습니다. 따라서 재정의와 관련이 있으므로 인터페이스 (또는 기본 클래스)는 다형성이며 구현자는 재정의하는 객체입니다 (동일한 메달의두면).

어쨌든 두 용어의 차이점은 c ++과 같은 다른 언어를 사용하여 더 잘 설명됩니다 .c ++의 다형성 객체는 기본 함수가 가상 인 경우 Java 대응 기능으로 작동하지만 메서드가 가상이 아닌 경우 코드 점프는 정적으로 해결됩니다 . 런타임에 확인되지 않은 트루 타입이므로 다형성에는 객체에 액세스하는 데 사용되는 인터페이스에 따라 객체가 다르게 동작하는 기능이 포함됩니다. 의사 코드로 예를 들어 보겠습니다.

class animal {
    public void makeRumor(){
        print("thump");
    }
}
class dog extends animal {
    public void makeRumor(){
        print("woff");
    }
}

animal a = new dog();
dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

(makeRumor가 가상이 아니라고 가정)

java는 이러한 수준의 다형성 (객체 슬라이싱이라고도 함)을 제공하지 않습니다.

동물 a = 새 개 (); 개 b = 새 개 ();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

두 경우 모두 woff 만 인쇄합니다. a와 b는 클래스 도그를 참조하기 때문에



동물 a = 새 개 (); a는 개로 구성되었으며 "woff"를 인쇄합니다. 당신이 그것을 thump를 인쇄하려면 그것을 캐스트해야합니다. ((animal) a) .makeRumor ()
Chris Cudmore

그것은 업 캐스트 참조이지만 개체는 여전히 개입니다. 동물이 되려면 명시 적으로 객체를 업 캐스트해야합니다.
Chris Cudmore

알아 냈습니다. 질문에 자바 태그가 추가되었습니다. 당신은 C ++에 대답했습니다. C ++에서 정확할 수 있습니다. Java에서는 정확합니다.
크리스 쿠드 모어

복사 생성자가 여기에 관여 할 때마다 발생해야하는 기준이다 fredosaurus.com/notes-cpp/oop-condestructors/...의 경우 세 경기; 명확하게 작성하기위한 새 연산자는 무시하십시오.
Lorenzo Boccaccia

0
import java.io.IOException;

class Super {

    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName() + " - I'm parent");
        return null;
    }

}

class SubOne extends Super {

    @Override
    protected Super getClassName(Super s)  {
        System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
        return null;
    }

}

class SubTwo extends Super {

    @Override
    protected Super getClassName(Super s) throws NullPointerException {
        System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
        return null;
    }

}

class SubThree extends Super {

    @Override
    protected SubThree getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
        return null;
    }

}

class SubFour extends Super {

    @Override
    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
        return null;
    }

}

class SubFive extends Super {

    @Override
    public Super getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
        return null;
    }

}

class SubSix extends Super {

    public Super getClassName(Super s, String ol) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
        return null;
    }

}

class SubSeven extends Super {

    public Super getClassName(SubSeven s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
        return null;
    }

}

public class Test{

    public static void main(String[] args) throws Exception {

        System.out.println("Overriding\n");

        Super s1 = new SubOne(); s1.getClassName(null);

        Super s2 = new SubTwo(); s2.getClassName(null);

        Super s3 = new SubThree(); s3.getClassName(null);

        Super s4 = new SubFour(); s4.getClassName(null);

        Super s5 = new SubFive(); s5.getClassName(null);

        System.out.println("Overloading\n");

        SubSix s6 = new SubSix(); s6.getClassName(null, null);

        s6 = new SubSix(); s6.getClassName(null);

        SubSeven s7 = new SubSeven(); s7.getClassName(s7);

        s7 = new SubSeven(); s7.getClassName(new Super());

    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.