views:

95

answers:

4

I have built a class in Mootools and extended it twice, such that there is a grandparent, parent, and child relationship:

var SomeClass1 = new Class({
  initialize: function() {
    // Code
  },
  doSomething: function() {
    // Code
  }
});

var SomeClass2 = new Class({
  Extends: SomeClass1,
  initialize: function() {
    this.parent();
  },
  doSomething: function() {
    this.parent();
    // Some code I don't want to run from Class3
  }
});

var SomeClass3 = new Class({
  Extends: SomeClass2,
  initialize: function() {
    this.parent();
  },
  doSomething: function() {
    this.grandParent();
  }
});

From Class3, the child, I need call the doSomething() method from Class1, the grandparent, without executing any code in Class2#doSomething(), the parent.

What I need is a grandParent() method to complement the Mootools parent(), but it appears that one does not exist.

What's the best way to accomplish this in either Mootools or pure JavaScript? Thanks.

UPDATE:

I should have mentioned: I realized that poor design has left me asking this question in the first place. A mixin would be ideal, but I inherited the code and don't have time for a refactor at the moment.

A: 

I don't have mootools at hand to test but...

Have you tried

(this.parent()).parent(); 

?

Eineki
That will still cause the parent method to be run.
chipotle_warrior
+1  A: 

this probably won't work for you but ... if you add SomeClass1 as a mixin and remove the local definition of doSomething from SomeClass3, then calling a method doSomething on the instance will call the SomeClass1.doSomething(); direct.

this may not be practical if your doSomething on SomeClass3 needs to run local/distinct code but you can work around it, perhaps.

http://www.jsfiddle.net/29MGa/1/

there must be a way of getting to the root of the inheritance chain from n-th level but i can't help you there. you ought to go to the mootools mailing list and post this in the hope that somebody from the core team answers (like ryan florence, aaron newton, christoph pojer etc). another good source is the mootools irc channel #mootools on irc.freenode.net.

good luck, please update this with your findings as you never know when one might need this.

update from irc:

<akaIDIOT> SomeClass1.prototype.doSomething.apply(this[, ...]);

<akaIDIOT> not as clean as .parent(), but Moo doesn't give you a grandparent :)

also the mixin gets a thumbs up of sorts:

<rpflo> d_mitar: I've often found that if I'm trying to do that it might make more sense for class 2 or 3 to be a mixin

<rpflo> but yeah, akaIDIOT's should work

Dimitar Christoff
Thanks for the mixin suggestion. That would work for me, however, I'm working with a large amount of existing code that leaves a bit to be desired and the refactor would take more time than I'm willing to give it at the moment.I'll be certain to update this thread with a solution should I find one.
chipotle_warrior
cool, i asked on irc about it and got some ideas, answer updated
Dimitar Christoff
A: 

Could you just call it on the grandparent class?

SomeClass1.doSomething.apply(this,arguments);

Or maybe even:

SomeClass1.prototype.doSomething.apply(this, arguments);

I'm not 100% sure how the MooTools classes work, but one of those suggestions should work.

Also, if you have functionality in doSomething() inside SomeClass2 that you don't want to be inherited for SomeClass3, why is SomeClass2 the parent class? You should be able to make another class to be the parent class that includes the functionality needed for both SomeClass2 and SomeClass3, and then allow each to override the doSomething() method in their own way.

gnarf
+1  A: 

As mentioned before, I bet using a mixin makes more sense here, but here ya go.

http://jsfiddle.net/rpflorence/24XJN/

var GrandParent = new Class({
    initialize: function(){
        console.log('init:GrandParent');
    },
    talk: function(){
        console.log('talk:GrandParent');
    }
});

var Parent = new Class({
    Extends: GrandParent,
    initialize: function(){
        this.parent();
        console.log('init:Parent');
    },
    talk: function(){
        console.log('talk:Parent');
    }
});

var Child = new Class({
    Extends: Parent,
    initialize: function(){
        this.parent();
        console.log('init:Child');
    },
    talk: function(){
        GrandParent.prototype.talk.apply(this);
        console.log('talk:Child');
    }
});
rpflo