How to override a method via prototype in a javascript object?

3

Hello

I'm studying javascript, but specifically Parasitic Combination Inheritance , and I came across overriding methods. It turns out that I created the following code:

var Base = function(nome, texto) {
    this.name = nome;
    this.text = texto;
    this.saudacao = function() {
          return this.text + ' ' + this.name;
    }
}

var heranca = function(p, f) {
    var pc = Object.create(p.prototype);
    f.prototype = pc;
    f.prototype.constructor = f;
}

var Dia = function(texto) {
    Base.call(this, 'Fulano? ', 'Tudo bem, ');
    this.newText = texto;
}
heranca(Base, Dia);
Dia.prototype.saudacao = function() {
    var msg = this.saudacao();
    return msg + ' ' + this.newText;
}

var ola = new Dia('Bom dia!');
alert(ola.saudacao());

When I run alert (ola.saudacao ()), I have the return of the parent class, not the override.

For testing, I changed the name of the "greetings" method of class "day" to "newSaudation" and, by running alert (new.audition ()), I get the correct output.

Apparently the code written in day.prototype.saudacao = function () {} does not even run (I added an alert ('!') on it and it did not work).

So here's the question: how to correctly work with javascript method overwriting without forgetting Parasitic Combination Inheritance ?

EDIT I will try to explain the practical application to clarify the question a bit. The objects used as examples are not in question, just their functionality.

Consider a class that calls itself "Kindness" and has the "Greetings" method.

When creating ...

var ola = new Gentileza ("José");

We can run ...

ola.Saudacao ();

And we will have: "Hello, Joseph."

Now, we need two other objects called "Day" and "Night" that are children of "Kindness." So we can create ...

var day = new Day ("Joseph");

And run ...

Now the message will be "Hello José. Good morning!". The first part of the message ("Hello, Joseph.") Was generated on the parent object (Kindness). The "Day" object inherited the greeting from the parent object and added "Good morning!" to the text.

For completion : I want my child class to inherit a parent class method and to complement it.

Thanks for your attention.

    
asked by anonymous 12.07.2017 / 18:16

3 answers

3

I think I understood what is confusing you. The operations you do, in summary, are:

  • Set inheritance of class base to class dia (note: it is a convention to use initials for uppercase name or constructor functions, but you have used lowercase)

  • Creates a new saudacao method in the dia prototype.

  • Creates instance of dia and executes method saudacao .

  • Your logic is that dia.prototype.saudacao should overwrite the existing greeting method in the database. This would be true if the method was in the base prototype. However, it is created in the instance ( this ):

    this.saudacao = function() {
          return this.text + ' ' + this.name;
    }
    

    And constructor of dia forces execution of constructor of base :

    base.call(this, 'Fulano? ', 'Tudo bem, ');
    

    So, the saudacao method executed in ola.saudacao() is defined within the base constructor, not what is in dia.prototype .

    Methods in the instance always take precedence over what's in the prototype chain. When you run ola.saudacao , the first thing that is checked is if the ola object itself has a saudacao property. And it does, because of that called base.call(this, ...) . Then this one runs. Only if it did not exist would it be checked dia.prototype and then base.prototype .

    You would get the result you want with the following code:

    var Base = function(nome, texto) {
        this.name = nome;
        this.text = texto;
    }
    
    Base.prototype.saudacao = function() {
    		return this.text + ' ' + this.name;
    }
    
    var heranca = function(p, f) {
        var pc = Object.create(p.prototype);
        f.prototype = pc;
        f.prototype.constructor = f;
    }
    
    var Dia = function(texto) {
        Base.call(this, 'Fulano? ', 'Tudo bem, ');
        this.newText = texto;
    }
    
    heranca(Base, Dia);
    
    Dia.prototype.saudacao = function() {
        var msg = Base.prototype.saudacao.call(this);
        return msg + ' ' + this.newText;
    }
    
    var ola = new Dia('Bom dia!');
    alert(ola.saudacao());

    But I do not think it's a good way. It seems that you want to do two things at once: override a method, but at the same time have access to the method overwritten from within the method that overrides it. It looks more like case for functional-style compositing than case for inheritance.

        
    12.07.2017 / 19:20
    2

    Okay, I get what you want to do.

    But you're pretty confused what "como" you're doing.

    Anyway, from what I understand what you're wondering is:

      

    How do I overwrite the prototype of a parent object in the child class.

    Before solving this, it is best to understand how to use Object Orientation correctly, because it is very confusing the example and why some things are being done X rather than Y.

    Anyway, there is a big inconsistency in the code below.

    See:

    Dia.prototype.saudacao = function() {
        var msg = this.saudacao();
        return msg + ' ' + this.newText;
    }
    

    You are - trying - to override a method and - without realizing it - you are creating an infinite loop, recursively.

    Anyway, I understood what you were trying to do up there.

    Change to something like this:

    Dia.prototype.saudacao = function() {
        return this.text + ' ' + this.name + ' ' + this.newText;
    }
    

    Now regarding the solution, the problem is somewhere in the heranca method:

    The way you are doing is that you are causing all this problem in code, method overload works normally if done in "padrão" way.

    The inheritance function should not be doing what we expected it to do, so it was impossible to resolve this issue without changing the code you did a lot.

    I just redo the code, basically it does the same thing and here it works fine.

    function Greet ( name , text ) {
        // Sobre o que falei acima de orientação a objetos, não vejo sentido do "nome" da pessoa estar nessa Classe. (só um exemplo)
    
        this._name = name ;
        this._text = text ;
        this._greet = function () {
            return this._text + ' ' + this._name ;
        }
    }
    
    function GoodDay ( greet ) {
        this.prototype = Greet ;
    
        Greet.call( this , 'Fulano? ' , 'Tudo bem, ' );
    
        this._greet = greet ;
    }
    
    GoodDay.prototype._greeting = function () {
        return this._text + ' ' + this._name + ' ' + this._greet ;
    }
    
    var hello = new GoodDay( 'Bom dia!' ) ;
    
    alert( hello._greeting() ) ;
    

    I broke my head to try to keep this heranca function that you created, but I could not solve it.

    In any case, if you analyze the situation and think in an Object Oriented way, you will see that it does not make much sense to have a function that assigns the inheritance between each class.

    For example: a dog, it É an animal (this is immutable), does not need someone to come and say that the dog will be an animal and this is basically what you are doing with this function heranca .

    I do not know if it was very clear, but it's +/- what I'm trying to explain.

        
    12.07.2017 / 20:52
    1

    I rewrote the code thinking about the problem and using the past tips:

        var inheritance = function(father, child) {
    	    var fatherCopy = Object.create(father.prototype);
        	child.prototype = fatherCopy;
        	child.prototype.constructor = child;
        }
    
        var Parent = function(msg) {
            this.text = msg;
        }
        Parent.prototype.message = function() {
        	return this.text;
        }
        var Oi = new Parent('Olá ');
        alert(Oi.message()); //Exibe "Olá"
        			
        var Child = function(nome) {
        	Parent.call(this, 'Olá ');
        	this.text2 = nome;
        }
        inheritance(Parent, Child);
        Child.prototype.message = function() {
        	return this.text + ' ' + this.text2;
        }
        			
        var Ai = new Child('Fulano');
        alert(Ai.message()); //Exibe "Olá Fulano"

    Problem solved.

        
    12.07.2017 / 21:50