[ 7 posts ]

Daniel Ji

  • Username: humblepie
  • Joined: Tue Feb 28, 2012 10:30 am
  • Posts: 147
  • GitHub: humblepie
  • Gists: humblepie
  • Offline
  • Profile

Creating subclasses with Y.Base.create()

Post Posted: Tue Jul 03, 2012 2:31 pm
+0-
So I had my first attempt at trying to use classical inheritance with YUI via Y.Base.create() to create subclasses. It wasn't a success.

The problem I ran into was that I forgot that the new ATTRs or methods/properties are added to the prototype. So even though I created instances of 2 subclasses, the internal state was shared b/t the two instances. My intent/desire was to create a subclass akin to a subclass in Java where each instance of a subclass has it's own state.

My use case was to subclass my own Y.View class.
Code:
var myParentView = Y.Base.create('MyParentView', Y.View, [],{...},{...});
var myFirstChildView = Y.Base.create('MyFirstChildView', myParentView, [],{...},{...});
var mySecondChildView = Y.Base.create('MySecondChildView', myParentView, [],{...},{...});
The above approach did not work out for me.

If I want to create subclasses, how can I accomplish this? I want code reuse and not shared state across all instances (via prototype).

Thanks.

Juan Ignacio Dopazo

YUI Contributor

  • Username: jdopazo
  • Joined: Fri Oct 02, 2009 5:39 am
  • Posts: 620
  • Location: Buenos Aires, Argentina
  • Twitter: juandopazo
  • GitHub: juandopazo
  • Gists: juandopazo
  • Offline
  • Profile

Re: Creating subclasses with Y.Base.create()

Post Posted: Tue Jul 03, 2012 6:55 pm
+0-
humblepie wrote:
The problem I ran into was that I forgot that the new ATTRs or methods/properties are added to the prototype. So even though I created instances of 2 subclasses, the internal state was shared b/t the two instances..

That shouldn't happen. YUI Attributes are per instance. Could you post a more complete example?

Daniel Ji

  • Username: humblepie
  • Joined: Tue Feb 28, 2012 10:30 am
  • Posts: 147
  • GitHub: humblepie
  • Gists: humblepie
  • Offline
  • Profile
Tags:

Re: Creating subclasses with Y.Base.create()

Post Posted: Fri Jul 06, 2012 9:41 am
+0-
Here you go. Both cvInstance and cvInstance2 share the same data even though I'd think they would have state that is independent. Namely,
Code:
cvInstance.get('time') === cvInstance2.get('time')  // same time
cvInstance.get('joe') === cvInstance2.get('joe')  // joe is 222 for both
cvInstance.lock() === cvInstance2.lock() // lock() return 'lock2' for both


Code:
<script type="text/javascript">
        YUI().use('base', 'view', 'node', function (Y) {
            Y.on('domready', function () {
                var msg,
                    childView1,
                    childView2,
                    childExt1,
                    childExt2,
                    parentView = Y.Base.create('ParentView', Y.View, [], {
                                getMine: function () {
                                    return 'super class';
                                },
                                viewns: 'y.view'
                            },
                            {
                                ATTRS: {
                                    time: {
                                        value: Y.Lang.now()
                                    }
                                }
                            }
                    );
                childExt1 = function () {
                    this.requiredInit = function () {
                        return '1';
                    };
                };
                childExt1.prototype = {
                    lock: function () {
                        return 'lock1';
                    }
                };
                childExt1.ATTRS = {
                    joe: {
                        value: 111
                    }
                };
                childExt2 = function () {
                    this.requiredInit = function () {
                        return '2';
                    };
                };
                childExt2.prototype = {
                    lock: function () {
                        return 'lock2';
                    }
                };
                childExt2.ATTRS = {
                    joe: {
                        value: 222
                    }
                };
                childView1 = Y.Base.mix(parentView, [childExt1]);
                childView2 = Y.Base.mix(parentView, [childExt2]);
                var cvInstance = new childView1();
                var cvInstance2 = new childView2();
            });
        });
    </script>

Juan Ignacio Dopazo

YUI Contributor

  • Username: jdopazo
  • Joined: Fri Oct 02, 2009 5:39 am
  • Posts: 620
  • Location: Buenos Aires, Argentina
  • Twitter: juandopazo
  • GitHub: juandopazo
  • Gists: juandopazo
  • Offline
  • Profile

Re: Creating subclasses with Y.Base.create()

Post Posted: Fri Jul 06, 2012 10:30 am
+0-
Ok. First of all, to set a default value of an attribute based on the return value of a function at the time of the creation of the instance, you should use valueFn:
Code:
ATTRS: {
  time: {
    valueFn: Y.Lang.now
  }
}

This will run Y.Lang.now() each time an instance is created.

Second, Y.Base.mix doesn't create a new class but rather modifies an existing one. So the first time you call mix() it copies the stuff from ChildExt1 into ParentView and the second time it does it again, overwriting the previous methods and values. That's why you get the same values, because childView1 == childView2.

My typical approach to solve that is to make a three extensions:
Code:
function MyViewBase() {
}
MyViewBase.prototype.foo = function () {};
MyViewBase.ATTRS = {};

function MyViewExt1() {
}
MyViewExt1.prototype.lock = function () {
  return 'lock 1';
};

function MyViewExt2(){
}
MyViewExt2.prototype.lock = function () {
  return 'lock 2';
};

//then create the two classes with Y.Base.create()
var ParentView1 = Y.Base.create('parentView1', Y.View, [MyViewBase, MyViewExt1]);
var ParentView2 = Y.Base.create('parentView2', Y.View, [MyViewBase, MyViewExt2]);

Nick Husher

YUI Contributor

  • Offline
  • Profile
Tags:

Re: Creating subclasses with Y.Base.create()

Post Posted: Fri Jul 06, 2012 10:33 am
+0-
What you're doing here is not the same as the snippet posted above. Look at the Y.Base.mix API documentation -- "Mixes in a list of extensions to an existing class." It alters the provided constructor, it doesn't create a subclass.

Here's an example of how you probably should be doing it:

my gist

Click here to see the revision history on this Gist.

Daniel Ji

  • Username: humblepie
  • Joined: Tue Feb 28, 2012 10:30 am
  • Posts: 147
  • GitHub: humblepie
  • Gists: humblepie
  • Offline
  • Profile
Tags:

Re: Creating subclasses with Y.Base.create()

Post Posted: Fri Jul 06, 2012 4:22 pm
+0-
Hi Juan,

Thanks for the tip on valueFn! That's exactly what I needed. In my code, I was instantiating a Y.ModelList only using 'value' and that's why it was shared b/t the subclasses.

The code sample you posted is great as well. It's a different approach that I didn't think about.

Daniel Ji

  • Username: humblepie
  • Joined: Tue Feb 28, 2012 10:30 am
  • Posts: 147
  • GitHub: humblepie
  • Gists: humblepie
  • Offline
  • Profile
Tags:

Re: Creating subclasses with Y.Base.create()

Post Posted: Fri Jul 06, 2012 4:24 pm
+0-
Hi Nick,

The solution you posted is what I tried initially! But I wasn't aware of the 'valueFn' property. I tried to refactor my sample code so that it doesn't use class extensions and simply uses the Y.Base.create() API and the subclasses behave as expected!

Thanks for the feedback :)
  [ 7 posts ]
Display posts from previous:  Sort by  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum