Changeset 7833
- Timestamp:
- 10/11/07 05:02:07 (9 months ago)
- Files:
-
- spinoffs/prototype/trunk/CHANGELOG (modified) (1 diff)
- spinoffs/prototype/trunk/src/base.js (modified) (3 diffs)
- spinoffs/prototype/trunk/test/unit/base.html (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
spinoffs/prototype/trunk/CHANGELOG
r7811 r7833 1 1 *SVN* 2 3 * Clean up the new class API. [sam, Tobie Langel] 4 - Add Class#addMethods for adding instance methods to classes. 5 - Remove Class.extend and Class.mixin. 6 - Class.create now takes a variable number of arguments: if the first argument is a class, the newly created class inherits from that class; all other arguments are treated as successive calls to addMethods. 2 7 3 8 * Fix contentloaded event initialization in IE. Closes #9457, #9488, #9707. [Mislav Marohnić] spinoffs/prototype/trunk/src/base.js
r7808 r7833 1 1 /* Based on Alex Arnell's inheritance implementation. */ 2 2 var Class = { 3 create: function(parent, properties) { 4 if (arguments.length == 1 && !Object.isFunction(parent)) 5 properties = parent, parent = null; 3 create: function() { 4 var parent = null, properties = $A(arguments); 5 if (Object.isFunction(properties[0])) 6 parent = properties.shift(); 6 7 7 8 function klass() { 8 9 this.initialize.apply(this, arguments); 9 10 } 10 11 12 Object.extend(klass, Class.Methods); 11 13 klass.superclass = parent; 12 14 klass.subclasses = []; 13 15 14 16 if (parent) { 15 17 var subclass = function() { }; … … 18 20 parent.subclasses.push(klass); 19 21 } 20 21 if (properties) Class.extend(klass, properties); 22 23 for (var i = 0; i < properties.length; i++) 24 klass.addMethods(properties[i]); 25 22 26 if (!klass.prototype.initialize) 23 27 klass.prototype.initialize = Prototype.emptyFunction; 24 28 25 29 klass.prototype.constructor = klass; 26 30 27 31 return klass; 28 }, 29 30 extend: function(destination, source) { 31 var ancestor = destination.superclass && destination.superclass.prototype; 32 } 33 }; 34 35 Class.Methods = { 36 addMethods: function(source) { 37 var ancestor = this.superclass && this.superclass.prototype; 32 38 33 39 for (var property in source) { … … 42 48 }); 43 49 } 44 destination.prototype[property] = value; 45 } 46 47 return destination; 48 }, 49 50 mixin: function(destination, source) { 51 return Object.extend(destination.prototype, source); 50 this.prototype[property] = value; 51 } 52 53 return this; 52 54 } 53 55 }; spinoffs/prototype/trunk/test/unit/base.html
r7808 r7833 74 74 // empty subclass 75 75 var Mouse = Class.create(Animal, {}); 76 76 77 //mixins 78 var Sellable = { 79 getValue: function(pricePerKilo) { 80 return this.weight * pricePerKilo; 81 }, 82 83 inspect: function() { 84 return '#<Sellable: #{weight}kg>'.interpolate(this); 85 } 86 }; 87 88 var Reproduceable = { 89 reproduce: function(partner) { 90 if (partner.constructor != this.constructor || partner.sex == this.sex) 91 return null; 92 var weight = this.weight / 10, sex = Math.random(1).round() ? 'male' : 'female'; 93 return new this.constructor('baby', weight, sex); 94 } 95 }; 96 97 // base class with mixin 98 var Plant = Class.create(Sellable, { 99 initialize: function(name, weight) { 100 this.name = name; 101 this.weight = weight; 102 }, 103 104 inspect: function() { 105 return '#<Plant: #{name}>'.interpolate(this); 106 } 107 }); 108 109 // subclass with mixin 110 var Dog = Class.create(Animal, Reproduceable, { 111 initialize: function($super, name, weight, sex) { 112 this.weight = weight; 113 this.sex = sex; 114 $super(name); 115 } 116 }); 117 118 // subclass with mixins 119 var Ox = Class.create(Animal, Sellable, Reproduceable, { 120 initialize: function($super, name, weight, sex) { 121 this.weight = weight; 122 this.sex = sex; 123 $super(name); 124 }, 125 126 eat: function(food) { 127 if (food instanceof Plant) 128 this.weight += food.weight; 129 }, 130 131 inspect: function() { 132 return '#<Ox: #{name}>'.interpolate(this); 133 } 134 }); 135 77 136 new Test.Unit.Runner({ 78 137 … … 420 479 testClassCreate: function() { with(this) { 421 480 assert(Object.isFunction(Animal), 'Animal is not a constructor'); 422 assertEnumEqual([Cat, Mouse ], Animal.subclasses);481 assertEnumEqual([Cat, Mouse, Dog, Ox], Animal.subclasses); 423 482 Animal.subclasses.each(function(subclass) { 424 483 assertEqual(Animal, subclass.superclass); … … 473 532 }}, 474 533 475 testClass Extend: function() { with(this) {534 testClassAddMethods: function() { with(this) { 476 535 var tom = new Cat('Tom'); 477 536 var jerry = new Mouse('Jerry'); 478 537 479 Class.extend(Animal,{538 Animal.addMethods({ 480 539 sleep: function() { 481 540 return this.say('ZZZ'); … … 483 542 }); 484 543 485 Class.extend(Mouse,{544 Mouse.addMethods({ 486 545 sleep: function($super) { 487 546 return $super() + " ... no, can't sleep! Gotta steal cheese!"; … … 499 558 assertUndefined(new Animal().escape); 500 559 501 Class.extend(Animal,{560 Animal.addMethods({ 502 561 sleep: function() { 503 562 return this.say('zZzZ'); … … 506 565 507 566 assertEqual("Jerry: zZzZ ... no, can't sleep! Gotta steal cheese!", jerry.sleep()); 508 }} 567 }}, 568 569 testBaseClassWithMixin: function() { with(this) { 570 var grass = new Plant('grass', 3); 571 assertRespondsTo('getValue', grass); 572 assertEqual('#<Plant: grass>', grass.inspect()); 573 }}, 574 575 testSubclassWithMixin: function() { with(this) { 576 var snoopy = new Dog('Snoopy', 12, 'male'); 577 assertRespondsTo('reproduce', snoopy); 578 }}, 579 580 testSubclassWithMixins: function() { with(this) { 581 var cow = new Ox('cow', 400, 'female'); 582 assertEqual('#<Ox: cow>', cow.inspect()); 583 assertRespondsTo('reproduce', cow); 584 assertRespondsTo('getValue', cow); 585 }} 509 586 510 587 }, 'testlog');