What are the differences between the concepts of polymorphism and superscript in OOP?

Asked

Viewed 1,740 times

12

I was a little confused when researching polymorphism. The concept of polymorphism resembles the concept of superscript. What are the differences between polymorphism and superscript in OOP?

  • 1

    In a nutshell: Polymorphism is the ability of an object to take various forms, so that an object X, if polymorphic, could take for example the shape of the object Y. One of the ways to implement polymorphism is through inheritance. Superscript is the ability of an object to offer an implementation for a behavior of the object whose form it assumed. Thus, if X inherits Y and overrides a behavior of Y, when X takes the form of Y (is used in a place where Y was expected) and such behavior is invoked, the implementation of X will be executed, not Y.

  • @Caffé, good answer

1 answer

11


They are related things. The superscript is used to achieve polymorphism. It is not the only mechanism but it is the most used in most languages mainstream.

Polymorphism is the characteristic that can use one object in place of another as if it were the expected object. For this to work properly it is necessary that the mechanism exists to ensure that the correct members are accessed.

A common situation is to expect one object and receive another that is descended from this expected one. If calling a method of this object, it will call the expected object method or the concrete descending object that was received?

Without the superscript, he would call the expected object method, from the father. But in general it is not what is desired. The superscript informs that this child object method should be used instead and meets the requirement of polymorphism.

Of course, there are cases where you do not want this replacement, you do not want polymorphism in a specific situation. There the superscript should not be used. Some languages handle this better than others.

In a question on the topic I talk about how can the mechanism work using the example of languages that do not possess polymorphism natively.

Using the example already given in another answer (fictitious language) see how polymorphism works:

class A {
    metodo1() { print "A"; }
    metodo2() { print "A"; }
}

class B extends A {
    override metodo1() { print "B"; }
    metodo2() { print "B"; }
}

void executa(A obj) { //note que ele receberá sempre algo do tipo A
    obj.metodo1();
    obj.metodo2();
}

executa(new A()); //imprime A e A
executa(new B()); //imprime B e A

The first example does not occur polymorphism. The expected object must be of the type A and it really is what is sent.

The second example occurs polymorphism in metodo1(). An object of the type has been sent B for a method I hoped to receive something like A. This is possible because the guy B derives from A, or meets all the requirements of A. As the method was superscripted, it will call the version of the concrete object, ie B.

But in the metodo2() polymorphism does not occur because there was no superscript. So as the method executa() expects something like A he will search in A even what to execute. He assumed no other form.

The most common way to accomplish this internally in the language is through a pointer table for the methods (vtable). When the superscript exists, the address of the derived class method is used instead of the address of the original method. When a call of this method is made, instead of simply calling the method by its known address, it will look in this table for the address to be called.

A more concrete example using abstract class would be to create a manipulator of log. Of course this does not make use of "good practices", it is a simplified form:

abstract class interface Log {
    bool save(string msg) {
        if (processMedia(msg)) {
            print "logou!";
            return true;
        } else {
            print "o log falhou!";
            return false;
        }
    }
    virtual bool processMedia(string msg);
}

class LogFile extends Log {
    override bool processMedia(string msg) { 
        try {
            //salva em arquivo aqui
            return true;
        } catch (IOException ex) {
            return false;
        }
    }
}

classe LogMail extends Log {
    override bool processMedia(string msg) {
        try {
            //envia por e-mail aqui
            return true;
        } catch (SMTPException ex) {
            return false;
        }
}

bool logou = new LogFile().save("deu um erro X aqui neste trecho");

I put in the Github for future reference.

This will save the error message to file. Note that called the method that only exists in the abstract type. No problem because it exists in the concrete type that is derived from Log. And within this method there will be a call to processMedia() that actually exists only in the derived class. There occurred a polymorphism.

Remembering that in interface always occurs the polymorphism (at least in most languages with this mechanism). Any operation that expects an interface will not be able to execute anything of the interface itself, after all it has no implementation. You should always call the contract method implemented on the particular type.

  • In your example 1 why the method 2() of class B does not have the @override which has the same class A signature ?

  • 3

    @Davidschrammel Because the intention is hide the parent class method instead of overwriting it in the sense of polymorphism. This example does not consider Java behavior. If you considered, the second output indicated would be wrong since in Java the methods are virtual by default and the superscript will always occur. This example probably considers the behavior of C#, where, on the other hand, if you are not overwriting a virtual method (which is indicated by the keyword override) but instead is hiding, it is recommended to make your intention explicit using the keyword new.

  • @Davidschrammel edited to make it clear that the language is fictitious and not Java. Neither C#. I had used an "abstract" example in the other question and followed it in this since it is a complement of the other. Example 2 is almost Java, but it is also not :)

  • 1

    Just to add that besides the example not being in Java, it does not apply to Java because, unlike the example, in Java it is not possible to hide (or "reintroduce", as it is called in other languages) an instance method of the parent class. The first example therefore considers language-specific details (it would serve in C# and Delphi, for example) and not object orientation in general (it does not serve in Java and Ruby, for example, because in these languages the method when redeclared in the child class will always be override).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.