IT TIP

가능한 한 쉽게 다형성을 설명하십시오.

itqueen 2020. 12. 9. 22:02
반응형

가능한 한 쉽게 다형성을 설명하십시오.


다형성을 이해하기 쉽게 설명 할 수있는 방법은 무엇입니까?

Type polymorphism 과 같이 인터넷과 책에서 주제에 대한 많은 정보를 찾을 수 있습니다 . 그러나 가능한 한 간단하게 만들도록합시다.


이것은 비슷한 질문 에서 내 대답 입니다. 다음은 유사 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 () 메서드의 특정 구현 동작에 따라 다릅니다.


두 개체가 동일한 메시지에 다른 동작으로 응답합니다. 보낸 사람은 신경 쓸 필요가 없습니다.


간단한 팝 뚜껑이있는 모든 캔은 같은 방식으로 열립니다.
인간으로서 당신은 당신이 찾을 수있는 모든 것을 Open () 할 수 있다는 것을 알고 있습니다.

개봉시 모든 캔이 동일한 방식으로 작동하는 것은 아닙니다.
일부는 견과류를 포함하고 일부는 튀어 나오는 가짜 뱀을 포함합니다.
결과는 캔이 "CanOfNuts"또는 "CanOfSnakes"인지 여부에 따라 캔의 유형에 따라 다르지만 여는 방법과는 관련이 없습니다. 어떤 캔이든 열 수 있다는 것을 알고 있으며 어떤 종류의 캔을 열 었는지에 따라 결정되는 일종의 결과를 얻을 수 있습니다.

pUnlabledCan-> Open (); // 견과류를 줄 수도 있고, 뱀을 줄 수도 있습니다. 우리가 그것을 부를 때까지 우리는 모른다

Open ()은 "Contents"(또는 반환 유형이 없다고 결정할 수 있음)의 일반 반환 유형을 가지고 있으므로 open은 항상 동일한 함수 서명을 갖습니다.

당신, 인간은 사용자 / 호출자입니다.
Open ()은 가상 / 다형성 함수입니다.
"Can"은 추상 기본 클래스입니다.
CanOfNuts 및 CanOfSnakes는 "Can"클래스의 다형성 자식입니다.
모든 캔이 열릴 수 있지만 구체적으로 수행하는 작업반환되는 내용의 특정 유형은 캔의 종류에 따라 정의됩니다.
pUnlabledCan을 볼 때 아는 것은 Open () 할 수 있고 내용을 반환한다는 것입니다. 다른 행동 (예 : 얼굴에 뱀이 터지는 등)은 특정 Can에 의해 결정됩니다.


다형성에 대한 가장 간단한 설명은 if / switch 문을 줄이는 방법 이라는 것입니다 .

또한 기존 클래스를 수정하지 않고 if / switch 문 (또는 다른 사람의 문)을 확장 할 수 있다는 이점도 있습니다.

예를 들어 Stream.NET 클래스 를 고려하십시오 . 다형성이 없으면 각 메서드가 다음과 같은 switch 문을 구현하는 단일 대규모 클래스가됩니다.

public class Stream
{
    public int Read(byte[] buffer, int offset, int count)
    {
        if (this.mode == "file")
        {
            // behave like a file stream
        }
        else if (this.mode == "network")
        {
            // behave like a network stream
        }
        else // etc.
    }
}

대신에 구체적인 유형 ( FileStream, NetworkStream)을 기반으로 구현을 자동으로 선택하여 런타임이보다 효율적인 방식으로 전환을 수행 할 수 있습니다.

public class FileStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a file stream
    }
}

public class NetworkStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a network stream
    }
}

Poly : 많은
Morphism : 형태 / 모양


배우 대 캐릭터 (또는 역할)


사과와 오렌지는 모두 과일입니다. 과일을 먹을 수 있습니다. 따라서 사과와 오렌지를 모두 먹을 수 있습니다.

키커? 당신은 그들을 다르게 먹습니다! 오렌지는 껍질을 벗기지 만 사과는 껍질을 벗기지 않습니다.

따라서 구현은 다르지만 최종 결과는 동일 하므로 과일을 먹습니다 .


오리처럼 걷고 오리처럼 꽥꽥 거리면 오리가 필요한 곳이면 어디에서나 오리처럼 취급 할 수 있습니다.


이것은 실제로 더 나은 기사입니다

다형성은 오브젝트가 동일하게 "보이지만"다른 방식으로 작동하도록합니다. 일반적인 예는 Speak () 메서드를 사용하여 동물 기본 클래스를 가져 오는 것입니다. 개 하위 클래스는 Bark를 내보내고 Pig 하위 클래스는 Oink를 방출합니다.

대부분의 사람들이 사용하는 5 초의 짧은 대답은 다른 개발자가 다형성에 대해 알아볼 수 있도록 오버로드 및 재정의입니다.


동일한 구문, 다른 의미.


그것을 설명하는 가장 간단한 방법 : 하나 이상의 대상에 적용 할 수있는 동사.

Hillel이 말했듯이 다른 모든 것은 주석입니다.


다형성은 일반적인 "부모"에 대한 지식에 의존하여 사물을 추상적으로 처리합니다 (개와 고양이의 부모로서 동물과 같은 계층을 생각해보십시오).

예를 들어, 모든 동물은 산소를들이 마실 수 있으며, 각각 다르게 수행 할 수 있지만 동물이 호흡 할 수있는 산소를 제공하는 시설을 설계하여 개와 고양이를 모두 지원할 수 있습니다.

약간의 추가로 Animal이 "추상적 인"식별자 (실제 "동물"이 아니라 동물 유형 만 있음)에도이 작업을 수행 할 수 있습니다.


다형성은 단일 유형의 위치에 둘 이상의 유형 값을 저장하는 것입니다.

이 질문에 대한 대부분의 다른 답변은 내 글을 쓰는 시점에서 실제로 다형성이 아닌 동적 디스패치를 ​​설명하고 있습니다.

동적 디스패치 는 다형성이 필요하지만 그 반대는 사실이 아닙니다. Java 또는 C #과 매우 유사하지만 System.Object에 멤버가없는 언어를 상상할 수 있습니다. 값으로 무엇이든하기 전에 타입 캐스팅이 필요합니다. 이 개념적 언어에는 다형성이있을 수 있지만 반드시 가상 메서드 나 다른 동적 디스패치 메커니즘은 아닙니다.

동적 디스패치는 관련이 있지만 별개의 개념이며 대부분의 다른 답변에서 충분히 설명됩니다. 그러나 일반적으로 객체 지향 언어에서 작동하는 방식 (첫 번째 ( 'this'또는 'Self') 인수 유형을 기반으로 함수 선택)이 작동 할 수있는 유일한 방법은 아닙니다. 선택이 모든 인수 유형에 적용되는 다중 디스패치 도 가능합니다.

마찬가지로 과부하 해결과 다중 디스패치는 서로 정확히 유사합니다. 오버로드 해결은 정적 유형에 적용되는 다중 디스패치이고, 다중 디스패치는 다형성 위치에 저장된 런타임 유형에 적용되는 오버로드 해결입니다.


다형성은 공통 속성을 기반으로 세계를 상자로 나누고 이러한 공통 속성 만 사용하려는 경우 주어진 상자의 항목을 상호 교환 가능한 것으로 취급합니다.


다형성 치료하는 기능입니다 서로 다른 그들이 것처럼 일을 같은 다음 그들 사이에 공유 된 정체성을 확립 그것을 이용하여 것.


다형성은 동일한 방법이 여러 클래스에 적용될 때 얻는 것입니다. 예를 들어, 문자열과 목록 모두 "Reverse"메소드를 가질 수 있습니다. 두 방법 모두 이름이 같습니다 ( "Reverse"). 두 방법 모두 매우 유사한 작업을 수행합니다 (모든 문자를 반대로하거나 목록의 요소 순서를 반대로 함). 그러나 각 "Reverse"메소드의 구현은 클래스에 따라 다르며 다릅니다. (즉, 문자열은 문자열처럼 반전되고 목록은 목록처럼 반전됩니다.)

은유를 사용하려면 프랑스 요리사 나 일본 요리사에게 "저녁 식사 만들기"라고 말할 수 있습니다. 각자 자신 만의 독특한 방식으로 "만찬 만들기"를 수행합니다.

실질적인 결과는 객체를 받아들이고 "Reverse"라고 부르는 "Reversing Engine"을 만들 수 있다는 것입니다. 개체에 Reverse 메서드가있는 한 Reversing Engine이 작동합니다.

셰프의 비유를 확장하기 위해 셰프에게 "저녁 식사 만들기"를 지시하는 "웨이터 봇"을 만들 수 있습니다. Waiterbot은 어떤 종류의 저녁 식사가 만들어 질지 알 필요가 없습니다. 요리사와 대화하고 있는지 확인하지 않아도됩니다. 중요한 것은 "요리사"(또는 소방관, 자판기 또는 애완 동물 사료 분배기)가 "저녁 식사를 만드십시오"라는 말을 들었을 때 무엇을해야하는지 알고 있다는 것입니다.

이것이 프로그래머로서 당신을 사게하는 것은 더 적은 코드 라인과 타입 안전성 또는 후기 바인딩입니다. 예를 들어 다음은 형식 안전성 및 초기 바인딩을 사용한 예제입니다 (내가 갈 때 구성하는 c와 유사한 언어).

class BankAccount {
    void SubtractMonthlyFee
}

class CheckingAccount : BankAccount {}

class SavingsAccount : BankAccount {}

AssessFee(BankAccount acct) {
    // This will work for any class derived from
    //   BankAccount; even classes that don't exist yet
    acct.SubtractMonthlyFee
}

main() {

    CheckingAccount chkAcct;
    SavingsAccount saveAcct;

    // both lines will compile, because both accounts
    //   derive from "BankAccount". If you try to pass in
    //   an object that doesn't, it won't compile, EVEN
    //   if the object has a "SubtractMonthlyFee" method.
    AssessFee(chkAcct);
    AssessFee(saveAcct);
}

다음은 형식 안전성이 없지만 후기 바인딩이있는 예입니다.

class DatabaseConnection {
    void ReleaseResources
}

class FileHandle {
    void ReleaseResources
}

FreeMemory(Object obj) {
    // This will work for any class that has a 
    //   "ReleaseResources" method (assuming all
    //   classes are ultimately derived from Object.
    obj.ReleaseResources
}

main() {

    DatabaseConnection dbConn;
    FileHandle fh;

    // You can pass in anything at all and it will
    //   compile just fine. But if you pass in an
    //   object that doesn't have a "ReleaseResources"
    //   method you'll get a run-time error.
    FreeMemory(dbConn);
    FreeMemory(fh);
    FreeMemory(acct); //FAIL! (but not until run-time)
}

좋은 예를 보려면 .NET ToString () 메서드를 살펴보십시오. 모든 클래스는 Object 클래스에서 파생되기 때문에 모든 클래스에 있습니다. 그러나 각 클래스는 자체적으로 의미있는 방식으로 ToString ()을 구현할 수 있습니다.

편집 : 간단! = 짧고, IMHO


다형성은 고급 알고리즘 코드가 여러 유형의 데이터에서 변경되지 않고 작동 할 수 있도록하는 언어 기능입니다.

This is done by ensuring the operations invoke the right implementation for each data type. Even in an OOP context (as per this question's tag), this "right implementation" may be resolved at compile-time or run-time (if your language supports both). In some languages like C++, compiler-supplied support for run-time polymorphism (i.e. virtual dispatch) is specific to OOP, whereas other types of polymorphism can also operate on data types that aren't objects (i.e. not struct or class instances, but may be builtin types like int or double).

( The types of polymorphism C++ supports are listed and contrasted in my answer: Polymorphism in c++ - even if you program other languages, it's potentially instructive )


The way I try and think of it is something that looks the same but can have different functionality depending on the instance. So you can have a type

interface IJobLoader

but depending on how it is used can have different functionality while still looking the same. You may have instances for BatchJobLoader, NightlyJobLoader etc

Maybe I am way off.


The term polymorphism can also apply to overloading functions. For example,

string MyFunc(ClassA anA);
string MyFunc(ClassB aB);

is a non-object oriented example of polymorphism.


Is the ability that objects have to respond to the same message in different ways.

For instance , in languages such as smalltalk, Ruby, Objective-C, you just have to send the message and they will respond.

 dao  = XmlDao.createNewInstance()    #obj 1
 dao.save( data )

 dao = RdbDao.createNewnewInstance()  #obj 2
 dao.save( data )

In this example two different objects, responded in different ways to the same messages: "createNewInstance() and save( obj )"

They act in different ways, to the same message. In the above languages, the classes might not even be in the same class hierarchy, it is enough that they respond to the message.

In languages such as Java, C++, C# etc. In order to assign the object to an object reference, they must share the same type hierarchy either by implementing the interface or by being subclass of a common class.

easy .. and simple.

Polymorphism is by far, the most important and relevant feature of object oriented programming.


It is a way to treat different things that can do something something similar in the same way without caring how they do it.

Let's say you have a game with a bunch of different types of Vehicles driving around such as Car, Truck, Skateboard, Airplane, etc... They all can Stop, but each Vehicle stops in a different way. Some Vehicles may need to shift down gears, and some may be able to come to a cold stop. Polymophism lets you do this

foreach (Vehicle v in Game.Vehicles)
{
   v.Stop();
}

The way that stop is implemented is deferred to the different Vehicles so your program doesn't have to care about it.


It's just a way to get old cold to call new code. You write some application that accepts some "Shape" interface with methods that others must implement (example - getArea). If someone comes up with a new whiz-bang way to implement that interface your old code can call that new code via the the getArea method.


The ability of an object of some type (e.g. a car) to act (e.g. brake) like one of another type (e.g. a vehicle) which usually suggests common ancestry (e.g. car is a subtype of vehicle) at one point in the type hierarchy.


Polymorphism is the Object Oriented solution to problem of passing a function to another function. In C you can do

 void h() { float x=3.0; printf("%f", x); }
 void k() { int y=5; printf("%i", y); }
 void g(void (*f)()) { f(); }
 g(h);  // output 3.0
 g(k);  // output 5

In C things get complicated if the function depends on additional parameters. If the functions h and k depend on different types of parameters you are in trouble and you must use casting. You have to store those parameters in a data structure, and pass a pointer to that data structure to g which passes it to h or k. h and k cast the pointer into a pointer to the proper structure and unpack the data. Very messy and very unsafe because of possible casting errors:

 void h(void *a) { float* x=(float*)a; printf("%f",*x); }
 void k(void *a) { int* y=(int*)a; printf("%i",*y); }
 void g(void (*f)(void *a),void *a) { f(a); }
 float x=3.0;
 int y=5;
 g(h,&x); // output x
 g(k,&y); // output y

So they invented polymorphism. h and k are promoted to classes and the actual functions to methods, the parameters are member variables of the respective class, h or k. Instead of passing the function around, you pass an instance of the class that contains the function you want. The instance contains its own parameters.

class Base { virtual public void call()=0; }
class H : public Base { float x; public void call() { printf("%f",x);} } h;
class K : public Base { int y; public void call() { printf("%i",y);} } k;
void g(Base &f) { f.call(); };
h.x=3.0;
k.y=5;
g(h); // output h.x
g(k); // output k.x

참고URL : https://stackoverflow.com/questions/210460/try-to-describe-polymorphism-as-easy-as-you-can

반응형