Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Class inheritance and composition patterns in Y...

ls_n
November 06, 2011

Class inheritance and composition patterns in YUI 3

Review of some strategies for class inheritance and composition, the relevant APIs and the reasons for choosing one approach over another. Watch the recording on the yuilibrary channel on youtube if you can.

ls_n

November 06, 2011
Tweet

Other Decks in Programming

Transcript

  1. Luke Smith From one, many From many, one Class inheritance

    and composition patterns in YUI Saturday, November 5, 11
  2. ★ Loader ★ CSS Reset and Grids ★ Module system

    ★ Custom Event system Saturday, November 5, 11
  3. • Pseudo-classical • Prototypal • Augmentation (Class A + Class

    B) • Plugins • Class extensions (mixins) • MVC Class structure strategies Saturday, November 5, 11
  4. Class structure strategies • Pseudo-classical • Prototypal • Augmentation •

    Plugins • Class extensions • MVC • Pseudo-classical • Prototypal Saturday, November 5, 11
  5. Artificial Native Class structure strategies • Pseudo-classical • Prototypal •

    Augmentation • Plugins • Class extensions • MVC • Pseudo-classical • Prototypal Saturday, November 5, 11
  6. Pseudo-classical function SubClass() { // constructor } SubClass.prototype = new

    SuperClass(); SubClass.prototype.someProperty = "booga!"; SubClass.prototype.someMethod = function () { ... }; ... SubClass.someStaticMethod = function () { ... }; ... Saturday, November 5, 11
  7. Pseudo-classical function SubClass() { // constructor } SubClass.prototype = new

    SuperClass(); SubClass.prototype.someProperty = "booga!"; SubClass.prototype.someMethod = function () { ... }; ... SubClass.someStaticMethod = function () { ... }; ... Y.extend = function (SubClass, SuperClass, proto, static) Saturday, November 5, 11
  8. Pseudo-classical function SubClass() { // constructor } Y.extend(SubClass, SuperClass); SubClass.prototype.someProperty

    = "booga!"; SubClass.prototype.someMethod = function () { ... }; ... SubClass.someStaticMethod = function () { ... }; ... Y.extend = function (SubClass, SuperClass, proto, static) Saturday, November 5, 11
  9. Pseudo-classical function SubClass() { // constructor } Y.extend(SubClass, SuperClass, {

    someProperty: "booga!", someMethod : function () { ... }, ... }); SubClass.someStaticMethod = function () { ... }; ... Y.extend = function (SubClass, SuperClass, proto, static) Saturday, November 5, 11
  10. Pseudo-classical function SubClass() { // constructor } Y.extend(SubClass, SuperClass, {

    someProperty: "booga!", someMethod : function () { ... }, ... }, { someStaticMethod: function () { ... }, ... }); Y.extend = function (SubClass, SuperClass, proto, static) Saturday, November 5, 11
  11. Pseudo-classical Y.SubClass = Y.extend( function() { // constructor }, /*

    extends */ SuperClass, { // Instance members someProperty: "booga!", someMethod : function () { ... } }, { // Static members someStaticMethod: function () { ... } }); Y.extend = function (SubClass, SuperClass, proto, static) Saturday, November 5, 11
  12. Y.extend() PROs • Creates a “clean” subclass relationship • no

    YUI class requirement • Preserves instanceof • SubClass.superclass (not super, but close) • Control superclass constructor execution Saturday, November 5, 11
  13. Y.extend() CONs • No multiple inheritance • Manual constructor chaining

    required • Constructor chaining is awkward • Constructor chaining may be costly Saturday, November 5, 11
  14. Y.extend() CONs • No multiple inheritance • Manual constructor chaining

    required • Constructor chaining is awkward • Constructor chaining may be costly function SubClass() { // Chain superclass constructor SubClass.superclass.constructor.apply(this, arguments); // My constructor stuff ... } Saturday, November 5, 11
  15. Y.extend() CONs • No multiple inheritance • Manual constructor chaining

    required • Constructor chaining is awkward • Constructor chaining may be costly function SubClass() { // Chain superclass constructor SubClass.superclass.constructor.apply(this, arguments); // My constructor stuff ... } AWKWARD Saturday, November 5, 11
  16. Y.extend() CONs • No multiple inheritance • Manual constructor chaining

    required • Constructor chaining is awkward • Constructor chaining may be costly function SubClass() { // Chain superclass constructor SubClass.superclass.constructor.apply(this, arguments); // My constructor stuff ... } AWKWARD COSTLY? Saturday, November 5, 11
  17. To sum up • Good for basic class inheritance •

    If you can extend Y.Base, there are more options Saturday, November 5, 11
  18. Prototypal Y.extend = function(SubClass, SuperClass,...) { var superProto = SuperClass.prototype,

    subProto = Y.Object(superProto); SubClass.prototype = subProto; ... Saturday, November 5, 11
  19. Prototypal Y.extend = function(SubClass, SuperClass,...) { var superProto = SuperClass.prototype,

    subProto = Y.Object(superProto); SubClass.prototype = subProto; ... Saturday, November 5, 11
  20. Prototypal Y.Object = (function () { function F() {} return

    function (obj) { F.prototype = obj; return new F(); }; })(); Saturday, November 5, 11
  21. Prototypal // Old and busted SubClass.prototype = new SuperClass(); Constructor

    SuperClass Prototype {} Constructor SubClass Prototype f(n) f(n) {} Saturday, November 5, 11
  22. Prototypal // Old and busted SubClass.prototype = new SuperClass(); Constructor

    SuperClass Prototype {} Constructor SubClass Prototype f(n) Constructor new f(n) {} Saturday, November 5, 11
  23. Prototypal // Old and busted SubClass.prototype = new SuperClass(); Constructor

    SuperClass Prototype {} Constructor SubClass Prototype f(n) Constructor new f(n) {} BAD Saturday, November 5, 11
  24. Prototypal // Old and busted SubClass.prototype = new SuperClass(); Constructor

    SuperClass Prototype {} Constructor SubClass f(n) f(n) Prototype {} Saturday, November 5, 11
  25. EMPTY Constructor (anon) Prototypal Y.Object = (function () { function

    F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); Constructor SuperClass Prototype Constructor SubClass Prototype f(n) f(n) {} {} Prototype {} {} Prototype f(n) Saturday, November 5, 11
  26. EMPTY Constructor (anon) Prototypal Y.Object = (function () { function

    F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); Constructor SuperClass Prototype Constructor SubClass Prototype f(n) f(n) {} {} Prototype {} {} Prototype f(n) Saturday, November 5, 11
  27. EMPTY Constructor (anon) Prototypal Y.Object = (function () { function

    F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); Constructor SuperClass Prototype Constructor SubClass Prototype f(n) new f(n) {} {} Prototype {} {} Prototype EMPTY Constructor f(n) Saturday, November 5, 11
  28. EMPTY Constructor (anon) Prototypal Y.Object = (function () { function

    F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); Constructor SuperClass Prototype Constructor SubClass f(n) f(n) {} Prototype {} Prototype {} {} Prototype f(n) Saturday, November 5, 11
  29. Prototypal Y.Object = (function () { function F() {} return

    function (obj) { F.prototype = obj; return new F(); }; })(); Any Object EMPTY Constructor (anon) f(n) {} {} Prototype Saturday, November 5, 11
  30. Prototypal Y.Object = (function () { function F() {} return

    function (obj) { F.prototype = obj; return new F(); }; })(); Any Object EMPTY Constructor (anon) f(n) {} {} Prototype Saturday, November 5, 11
  31. Prototypal Y.Object = (function () { function F() {} return

    function (obj) { F.prototype = obj; return new F(); }; })(); Any Object EMPTY Constructor (anon) f(n) New Object {} {} Prototype EMPTY Constructor (anon) f(n) Prototype {} Saturday, November 5, 11
  32. Factory constructor function Set() { var that = (this instanceof

    Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that; } Saturday, November 5, 11
  33. Factory constructor function Set() { var that = (this instanceof

    Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that; } var set = new Set(‘a’,’b’); Saturday, November 5, 11
  34. Factory constructor function Set() { var that = (this instanceof

    Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that; } var set = new Set(‘a’,’b’); set instanceof Set; // true Saturday, November 5, 11
  35. Factory constructor function Set() { var that = (this instanceof

    Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that; } var set = Set(‘a’,’b’); // <-- OOPS! I forgot 'new'! Saturday, November 5, 11
  36. Factory constructor function Set() { var that = (this instanceof

    Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that; } var set = Set(‘a’,’b’); set instanceof Set; // true Saturday, November 5, 11
  37. Y.Object() PROs • Avoids copying a lot of properties •

    Can be used to make factory constructors • Can be used to store original values for revert • Any object can be the prototype • Avoids class explosion Saturday, November 5, 11
  38. Y.Object() CONs • No multiple inheritance • Factory constructor can

    promote sloppiness • Can’t use hasOwnProperty in for/in loops Saturday, November 5, 11
  39. To sum up • Useful for some internal logic patterns

    • Not a good fit for most web app problems • Common use suggests need for a constructor Saturday, November 5, 11
  40. To sum up var account1 = Y.Object(accountProto); account1.id = 1234;

    account1.holder = 'John Q. Consumer'; var account2 = Y.Object(accountProto); account2.id = 1235; account2.holder = 'Jane B. Investor'; • Useful for some internal logic patterns • Not a good fit for most web app problems • Common use suggests need for a constructor Saturday, November 5, 11
  41. To sum up var account1 = Y.Object(accountProto); account1.id = 1234;

    account1.holder = 'John Q. Consumer'; var account2 = Y.Object(accountProto); account2.id = 1235; account2.holder = 'Jane B. Investor'; • Useful for some internal logic patterns • Not a good fit for most web app problems • Common use suggests need for a constructor Saturday, November 5, 11
  42. To sum up var account1 = Y.Object(accountProto); account1.id = 1234;

    account1.holder = 'John Q. Consumer'; var account2 = Y.Object(accountProto); account2.id = 1235; account2.holder = 'Jane B. Investor'; CONSTRUC TOR • Useful for some internal logic patterns • Not a good fit for most web app problems • Common use suggests need for a constructor Saturday, November 5, 11
  43. To sum up function Account(id, holder) { this.id = id;

    this.holder = holder; } var account1 = new Account(1234, 'John Q. Consumer'); var account2 = new Account(1235, 'Jane B. Invester'); • Useful for some internal logic patterns • Not a good fit for most web app problems • Common use suggests need for a constructor Saturday, November 5, 11
  44. Class structure strategies Native ✓ Pseudo-classical ✓ Prototypal Artificial •

    Augmentation • Plugins • Class extensions • MVC Saturday, November 5, 11
  45. Class structure strategies Native ✓ Pseudo-classical ✓ Prototypal Artificial •

    Augmentation • Plugins • Class extensions • MVC Saturday, November 5, 11
  46. Augmentation Y.ModelList = Y.extend( function () { /* constructor */

    ModeList.superclass.constructor.apply(this, arguments); }, Y.Base, { /* prototype */ }, { /* static */ }); Y.augment(Y.ModelList, Y.ArrayList); Y.augment = function (to, from, force, whitelist, config) Saturday, November 5, 11
  47. Augmentation Y.ModelList = Y.extend( function () { /* constructor */

    ModeList.superclass.constructor.apply(this, arguments); }, Y.Base, { /* prototype */ }, { /* static */ }); Y.augment(Y.ModelList, Y.ArrayList); Y.augment = function (to, from, force, whitelist, config) Saturday, November 5, 11
  48. Augmentation Y.ModelList = Y.extend( function () { /* constructor */

    ModeList.superclass.constructor.apply(this, arguments); }, Y.Base, { /* prototype */ }, { /* static */ }); Y.augment(Y.ModelList, Y.ArrayList); Y.augment = function (to, from, force, whitelist, config) Saturday, November 5, 11
  49. Augmentation Y.augment(Y.ModelList, Y.ArrayList); var list = new Y.ModelList({ ... });

    list.each(function (item) { ... }); ModelList Prototype Constructor create init ArrayList Prototype each item Constructor Saturday, November 5, 11
  50. Augmentation Y.augment(Y.ModelList, Y.ArrayList); var list = new Y.ModelList({ ... });

    list.each(function (item) { ... }); ModelList Prototype Constructor create init ArrayList Prototype each item Constructor each item augment Saturday, November 5, 11
  51. Augmentation Y.augment(Y.ModelList, Y.ArrayList); var list = new Y.ModelList({ ... });

    list.each(function (item) { ... }); ModelList Prototype Constructor create init ArrayList Prototype each item Constructor each item new Constructor Saturday, November 5, 11
  52. list ModelList Prototype Constructor create init each item Augmentation Y.augment(Y.ModelList,

    Y.ArrayList); var list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init ArrayList Prototype each item Constructor each item Prototype create init each item Saturday, November 5, 11
  53. list ModelList Prototype Constructor create init each item Augmentation Y.augment(Y.ModelList,

    Y.ArrayList); var list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init ArrayList Prototype each item Constructor each item Prototype Saturday, November 5, 11
  54. list ArrayList Prototype each item Constructor Augmentation Y.augment(Y.ModelList, Y.ArrayList); var

    list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init Prototype each item Saturday, November 5, 11
  55. list ArrayList Prototype each item Constructor Augmentation Y.augment(Y.ModelList, Y.ArrayList); var

    list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init Prototype each item each each Saturday, November 5, 11
  56. list ArrayList Prototype each item Constructor Augmentation Y.augment(Y.ModelList, Y.ArrayList); var

    list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init Prototype each item each Saturday, November 5, 11
  57. list item each ArrayList Prototype each item Constructor Augmentation Y.augment(Y.ModelList,

    Y.ArrayList); var list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init Prototype each item 1. Copy each Saturday, November 5, 11
  58. list item each ArrayList Prototype each item Constructor Augmentation Y.augment(Y.ModelList,

    Y.ArrayList); var list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init Prototype each item Constructor 1. Copy 2. Construct each Saturday, November 5, 11
  59. list item each ArrayList Prototype each item Constructor Augmentation Y.augment(Y.ModelList,

    Y.ArrayList); var list = new Y.ModelList({ ... }); list.each(function (item) { ... }); ModelList Prototype Constructor create init Prototype each item each 1. Copy 2. Construct 3. Execute Saturday, November 5, 11
  60. Augmentation Y.augment(Y.HistoryBase, Y.EventTarget, null, null, { emitFacade : true, prefix

    : 'history', preventable: false, queueable : true }); Y.augment = function (to, from, force, whitelist, config) Saturday, November 5, 11
  61. Y.augment() PROs • Defers constructor overhead • Can augment with

    multiple classes • Supports class or instance augmentation • No YUI class requirement Saturday, November 5, 11
  62. Y.augment() CONs • First augmented method call is costly •

    instanceof is false for augmenting classes • Consumes more memory • Limited control of constructor invocation Saturday, November 5, 11
  63. To sum up • Use it to simulate lazy multiple

    inheritance • Y.Base-based classes should use class extensions • Beware the diamond problem • Weigh the importance of constructor deferral Saturday, November 5, 11
  64. To sum up • Use it to simulate lazy multiple

    inheritance • Y.Base-based classes should use class extensions • Beware the diamond problem • Weigh the importance of constructor deferral Y.SubClass = Y.extend( function () { Y.SuperClass.apply(this, arguments); Y.EventTarget.apply(this, { /* config */ }); }, Y.SuperClass, // <-- one "official" extention class Y.mix({ /* prototype */ }, Y.EventTarget.prototype), { /* static */ }); Saturday, November 5, 11
  65. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock',

    true); overlay.unplug('dd'); Overlay Attributes x y Constructor Saturday, November 5, 11
  66. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock',

    true); overlay.unplug('dd'); Overlay Attributes x y Constructor Constructor Saturday, November 5, 11
  67. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock',

    true); overlay.unplug('dd'); Overlay Attributes x y Constructor overlay Attributes x y Saturday, November 5, 11
  68. overlay Attributes x y Plugins var overlay = new Y.Overlay({

    ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock', true); overlay.unplug('dd'); Overlay ATTRS x y Constructor Plugin.Drag ATTRS lock Constructor Saturday, November 5, 11
  69. overlay Attributes x y Plugins var overlay = new Y.Overlay({

    ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock', true); overlay.unplug('dd'); Overlay ATTRS x y Constructor Plugin.Drag ATTRS lock Constructor Constructor Saturday, November 5, 11
  70. overlay Attributes x y Plugins var overlay = new Y.Overlay({

    ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock', true); overlay.unplug('dd'); Overlay ATTRS x y Constructor Plugin.Drag ATTRS lock Constructor overlay.dd Attributes lock Saturday, November 5, 11
  71. overlay Attributes x y Plugins var overlay = new Y.Overlay({

    ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock', true); overlay.unplug('dd'); Overlay ATTRS x y Constructor Plugin.Drag ATTRS lock Constructor overlay.dd Attributes lock dd Saturday, November 5, 11
  72. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock',

    true); overlay.unplug('dd'); Overlay ATTRS x y Constructor Plugin.Drag ATTRS lock Constructor overlay Attributes x y overlay.dd Attributes lock dd Saturday, November 5, 11
  73. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock',

    true); overlay.unplug('dd'); Overlay ATTRS x y Constructor Plugin.Drag ATTRS lock Constructor overlay Attributes x y overlay.dd Attributes lock dd Saturday, November 5, 11
  74. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set('lock',

    true); overlay.unplug('dd'); Overlay ATTRS x y Constructor Plugin.Drag ATTRS lock Constructor overlay Attributes x y Saturday, November 5, 11
  75. The requirements • Y.Plugin.Host (free in Y.Base, or add with

    Y.augment) Host class Plugin class • Static NS property Saturday, November 5, 11
  76. The requirements • Y.Plugin.Host (free in Y.Base, or add with

    Y.augment) Host class Plugin class • Static NS property That’s it Saturday, November 5, 11
  77. Plugins (instance) Y.Plugin.Host.prototype.plug = function (Plugin, config) { ... if

    (Plugin && Plugin.NS) { config.host = this; this[Plugin.NS] = new Plugin(config); } }; Saturday, November 5, 11
  78. Plugins (instance) Y.Plugin.Host.prototype.plug = function (Plugin, config) { ... if

    (Plugin && Plugin.NS) { config.host = this; this[Plugin.NS] = new Plugin(config); } }; overlay.dd.set('lock', true); overlay.unplug('dd'); Saturday, November 5, 11
  79. The contract SHOULD ✓ Expect an object constructor argument with

    ‘host’ property Saturday, November 5, 11
  80. The contract ✓ Provide namespaced API ✓ Modify core behavior

    via events or AOP MAY SHOULD ✓ Expect an object constructor argument with ‘host’ property Saturday, November 5, 11
  81. The contract ✓ Provide namespaced API ✓ Modify core behavior

    via events or AOP MAY MUST ✓ Remove all traces when unplugged SHOULD ✓ Expect an object constructor argument with ‘host’ property Saturday, November 5, 11
  82. The contract ✓ Provide namespaced API ✓ Modify core behavior

    via events or AOP MAY MUST ✓ Remove all traces when unplugged MUST NOT ✓ Modify host directly other than add the namespace SHOULD ✓ Expect an object constructor argument with ‘host’ property Saturday, November 5, 11
  83. Plugins (class) Y.Plugin.Host.plug(Y.Overlay, Y.Plugin.Drag, { handles: ['.yui3-widget-hd'] }); var overlay

    = new Y.Overlay({ ... }); overlay.dd.set('lock', true); Saturday, November 5, 11
  84. Plugin PROs • Avoids method/property naming collisions • Preserves host

    behavior when unplug()ed • Plug classes or instances • Generic plugins can work for multiple host types • Works on Nodes Saturday, November 5, 11
  85. Plugin CONs • Fragments API • Plugin contract to restore

    host can add code weight • Difficult to manage competing plugins • plug() could use a little sugar Saturday, November 5, 11
  86. to sum up • Flexible • Better in smaller numbers

    • Class Plugins vs Augmentation? • Free with Y.Base-based classes and Y.Nodes (have I mentioned that you should use Y.Base?) Saturday, November 5, 11
  87. Class extensions Y.extend = function (SubClass, SuperClass, proto, static) Y.SubClass

    = Y.extend( { someProperty: ‘booga!’, someMethod : function () { ... } }, { function() { SubClass.superclass.constructor.apply(this, arguments); }, /* extends */ Y.Base NAME: ‘subsub’, /* NAME */ ‘subsub’, ATTRS: { ... } }); Saturday, November 5, 11
  88. Class extensions Y.extend = function (SubClass, SuperClass, proto, static) Y.SubClass

    = Y.extend( { someProperty: ‘booga!’, someMethod : function () { ... } }, { /* extends */ Y.Base NAME: ‘subsub’, /* NAME */ ‘subsub’, ATTRS: { ... } }); Saturday, November 5, 11
  89. Class extensions Y.extend = function (SubClass, SuperClass, proto, static) Y.SubClass

    = Y.extend( { someProperty: ‘booga!’, someMethod : function () { ... } }, { /* extends */ Y.Base NAME: ‘subsub’, [], // <-- class extensions! /* NAME */ ‘subsub’, ATTRS: { ... } }); Saturday, November 5, 11
  90. Class extensions Y.SubClass = Y.extend( { someProperty: ‘booga!’, someMethod :

    function () { ... } }, { /* extends */ Y.Base NAME: ‘subsub’, [], // <-- class extensions! /* NAME */ ‘subsub’, Y.Base.create = function(NAME, SuperClass, ext, proto, static) ATTRS: { ... } }); Saturday, November 5, 11
  91. Class extensions Y.Base.create = function(NAME, SuperClass, ext, proto, static) Y.LineSeries

    = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ }); Saturday, November 5, 11
  92. Class extensions Y.Base.create = function(NAME, SuperClass, ext, proto, static) Y.LineSeries

    = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ }); Y.ComboSeries = Y.Base.create('comboSeries', Y.CartesianSeries, [ Y.Fills, Y.Lines, Y.Plots ], { /* Glue Y.Fills etc APIs to Y.CartesianSeries APIs */ }, { ATTRS: { ... } }); Saturday, November 5, 11
  93. Class extensions Y.Base.create = function(NAME, SuperClass, ext, proto, static) Y.LineSeries

    = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ }); Y.ComboSeries = Y.Base.create('comboSeries', Y.CartesianSeries, [ Y.Fills, Y.Lines, Y.Plots ], { /* Glue Y.Fills etc APIs to Y.CartesianSeries APIs */ }, { ATTRS: { ... } }); Saturday, November 5, 11
  94. LineSeries Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],

    { ... }); var series = new Y.LineSeries({ ... }); Lines Constructor Constructor Prototype ATTRS ATTRS Prototype Cartesian Constructor ATTRS Prototype Saturday, November 5, 11
  95. LineSeries Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],

    { ... }); var series = new Y.LineSeries({ ... }); Lines Constructor Constructor Prototype ATTRS ATTRS Prototype Cartesian Constructor ATTRS Prototype Constructor Constructor Saturday, November 5, 11
  96. LineSeries Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],

    { ... }); var series = new Y.LineSeries({ ... }); Prototype ATTRS Lines Constructor ATTRS Prototype Cartesian Constructor ATTRS Prototype Constructor Constructor Constructor Constructor Saturday, November 5, 11
  97. LineSeries Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],

    { ... }); var series = new Y.LineSeries({ ... }); Prototype ATTRS Constructor ATTRS Cartesian Constructor ATTRS Prototype direction type Lines Constructor ATTRS Prototype type Saturday, November 5, 11
  98. LineSeries Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],

    { ... }); var series = new Y.LineSeries({ ... }); Prototype Constructor ATTRS Cartesian Constructor ATTRS Prototype direction type Lines Constructor ATTRS Prototype type styles Saturday, November 5, 11
  99. LineSeries Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],

    { ... }); var series = new Y.LineSeries({ ... }); Prototype Constructor ATTRS Cartesian Constructor ATTRS Prototype direction type Lines Constructor ATTRS Prototype type direction type type styles Saturday, November 5, 11
  100. LineSeries Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],

    { ... }); var series = new Y.LineSeries({ ... }); Prototype Constructor ATTRS Cartesian Constructor ATTRS Prototype direction type Lines Constructor ATTRS Prototype type direction type styles Saturday, November 5, 11
  101. Lines Constructor ATTRS Prototype type LineSeries Class extensions Y.LineSeries =

    Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Prototype Constructor Cartesian Constructor ATTRS Prototype direction type ATTRS direction type styles Prototype Saturday, November 5, 11
  102. Lines Constructor Prototype ATTRS drawLines LineSeries Class extensions Y.LineSeries =

    Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Prototype Constructor ATTRS Prototype Cartesian Constructor ATTRS Prototype draw Saturday, November 5, 11
  103. Lines Constructor Prototype ATTRS drawLines LineSeries Class extensions Y.LineSeries =

    Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Constructor ATTRS Prototype Cartesian Constructor ATTRS Prototype draw Saturday, November 5, 11
  104. Lines Constructor Prototype ATTRS drawLines LineSeries Class extensions Y.LineSeries =

    Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Constructor ATTRS Prototype Cartesian Constructor ATTRS Prototype draw Prototype draw Prototype draw drawLines drawSeries Saturday, November 5, 11
  105. Lines Constructor Prototype ATTRS drawLines LineSeries Class extensions Y.LineSeries =

    Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Constructor ATTRS Cartesian Constructor ATTRS Prototype draw Prototype initializer Prototype initializer initializer initializer initializer initializer Saturday, November 5, 11
  106. Class extensions Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], {

    ... }); var series = new Y.LineSeries({ ... }); 1. Constructors are called 2. Attributes are set 3. initializers are called Saturday, November 5, 11
  107. Two types of extensions 1. Class decoration 2.Core functionality Add

    feature APIs and Attributes Satisfy abstract class implementation Saturday, November 5, 11
  108. Class extensions Y.Base.create = function(NAME, SuperClass, ext, proto, static) Y.Overlay

    = Y.Base.create('overlay', Y.Widget, [ Y.WidgetStdMod, Y.WidgetPosition, Y.WidgetStack, Y.WidgetPosition, Y.WidgetPositionConstrain ]); Saturday, November 5, 11
  109. Class extensions Y.Base.mix = function(Class, ext) Y.Slider = Y.Base.create('slider', Y.SliderBase,

    [Y.SliderValueRange]); Y.Base.mix(Y.Slider, [Y.ClickableRail]); Saturday, November 5, 11
  110. Extensions PROs • Promotes code reuse across environments • Feature

    APIs are added to the prototype • Can be used to mimic MVC breakdown Saturday, November 5, 11
  111. Extensions CONs • Requires Y.Base • Initialization overhead • Class

    definition only (no instance feature additions) • Does not work on Nodes • Increased potential for accidental name collisions Saturday, November 5, 11
  112. Extension vs Plugin • Extensions can be used to contribute

    core behavior • Extensions modify the class prototype, plugins are always namespaced • Feature extension constructors are always executed, plugin constructors on plug() • Feature APIs/attributes on the prototype vs class plugins in namespace is a stylistic choice Saturday, November 5, 11
  113. Invest in the future (and use Y.Base) (and join us

    in #yui) Saturday, November 5, 11