| Page 1 of 1 | [ 7 posts ] |
|
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, [],{...},{...}); The above approach did not work out for me.var myFirstChildView = Y.Base.create('MyFirstChildView', myParentView, [],{...},{...}); var mySecondChildView = Y.Base.create('MySecondChildView', myParentView, [],{...},{...}); 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 DopazoYUI Contributor
|
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? |
|
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 DopazoYUI Contributor
|
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]); |
|
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 gistClick here to see the revision history on this Gist. |
|
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. |
|
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 |
| Page 1 of 1 | [ 7 posts ] |
| 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 |
© 2006-2013 Yahoo! Inc. All rights reserved.
All code on this site is licensed under the BSD License unless stated otherwise.
About This Site · Security Contact Info
Powered by phpBB® Forum Software © phpBB Group