What are the differences between the concepts of Polymorphism and Overwritten in OOP?

11

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

    
asked by anonymous 27.09.2015 / 19:58

1 answer

11

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

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

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

Without the override, it would call the expected object's parent method. But in general it's not what you want. The override informs that this child object method must be used in place and meets the polymorphism requirement.

Obviously there are cases where this substitution is not desired, the polymorphism in a specific situation is not wanted. There, the superscript should not be used. Some languages deal better with this than others.

In a question about the topic I talk about how the engine works using the example of languages that do not have the polymorphism natively.

Using the example already given in another answer (fictional language) see how the 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 type A and it really is what is sent.

The second example shows polymorphism in metodo1() . An object of type B was sent to a method expecting to receive something of type A . This is possible because the type B is derived from A , that is, it meets all requirements of A . As the method has been overwritten, it will call the concrete object version, that is B .

But in% w / o% the polymorphism does not occur because there was no override. So since the metodo2() method expects something of type executa() it will look at A even what to execute. He did not take it any other way.

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

A more concrete example using abstract class would be to create a log handler. 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");

This will write the error message to file. Note that you called the method that only exists in the abstract type. No problem because it exists in the concrete type that is derived from A . And within this method there will be a call to Log that only exists in fact in the derived class. There was a polymorphism.

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

    
27.09.2015 / 20:23