Changeset 7004
- Timestamp:
- 06/11/07 19:27:12 (1 year ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
spinoffs/prototype/branches/inheritance/src/base.js
r6813 r7004 2 2 var Class = { 3 3 extend: function(parent, methods) { 4 if (arguments.length == 1) {5 methods = parent; parent = null;6 }7 4 var method = function() { 8 5 if (!Class.extending) this.initialize.apply(this, arguments); 9 6 }; 10 7 8 method.superclass = parent; 9 method.subclasses = []; 10 11 11 if (typeof parent === 'function') { 12 12 Class.extending = true; 13 13 method.prototype = new parent(); 14 method.prototype.constructor = method; 15 16 parent.subclasses.push(method); 17 14 18 delete Class.extending; 15 19 } 20 21 if (methods) Class.add(method, methods); 22 23 return method; 24 }, 25 26 add: function(destination, source) { 27 for (var name in source) Class.inherit(destination, source, name); 28 return destination; 29 }, 16 30 17 if (methods) Class.inherit(method.prototype, methods);18 return method;19 },20 21 31 inherit: function(destination, source, name) { 22 if (arguments.length === 3) { 23 var ancestor = destination[name], descendant = source[name], 24 method = descendant; 25 32 var prototype = destination.prototype; 33 if (prototype[name] && typeof source[name] === 'function') { 34 var ancestor = prototype[name], descendant = source[name], method = descendant; 26 35 descendant = function() { 27 36 var ref = this.parent; this.parent = ancestor; … … 30 39 return result; 31 40 }; 32 41 33 42 Object.extend(descendant, { 34 43 valueOf: function() { return method; }, 35 44 toString: function() { return method.toString(); } 36 45 }); 37 destination[name] = descendant; 38 } else { 39 for (var property in source) { 40 if (destination[property] && typeof source[property] === 'function') 41 Class.inherit(destination, source, property); 42 else destination[property] = source[property]; 46 prototype[name] = descendant; 47 } else prototype[name] = source[name]; 48 49 if (destination.subclasses && destination.subclasses.length > 0) { 50 for (var i = 0, subclass; subclass = destination.subclasses[i]; i++) { 51 Class.extending = true; 52 Object.extend(subclass.prototype, new destination()); 53 subclass.prototype.constructor = subclass; 54 delete Class.extending; 55 Class.inherit(subclass, destination.prototype, name); 43 56 } 44 57 } 45 return destination;46 58 }, 47 59 48 60 mixin: function(destination, source) { 49 return Object.extend(destination .prototype, source);50 } 51 }; 52 53 Class.create = function() { 54 return Class.extend.apply(this, arguments);61 return Object.extend(destination, source); 62 }, 63 64 create: function(methods) { 65 return Class.extend(null, methods); 66 } 55 67 }; 56 68 spinoffs/prototype/branches/inheritance/test/unit/base.html
r6723 r7004 56 56 57 57 var globalBindTest = null; 58 59 60 // base class 61 var Animal = Class.create({ 62 initialize: function(name) { 63 this.name = name; 64 }, 65 name: "", 66 eat: function() { 67 return this.say("Yum!"); 68 }, 69 say: function(message) { 70 return this.name + ": " + message; 71 } 72 }); 73 74 // subclass that augments a method 75 var Cat = Class.extend(Animal, { 76 eat: function(food) { 77 if (food instanceof Mouse) return this.parent(); 78 else return this.say("Yuk! I only eat mice."); 79 } 80 }); 81 82 // empty subclass 83 var Mouse = Class.extend(Animal); 58 84 59 85 new Test.Unit.Runner({ … … 285 311 assert(Prototype.Browser.Gecko); 286 312 } 313 }}, 314 315 testInstantiation: function() { with(this) { 316 var pet = new Animal("Nibbles"); 317 assertEqual("Nibbles", pet.name, "property not initialized"); 318 assertEqual('Nibbles: Hi!', pet.say('Hi!')); 319 assertEqual(Animal, pet.constructor, "bad constructor reference"); 320 assertUndefined(pet.superclass); 321 }}, 322 323 testInheritance: function() { with(this) { 324 var tom = new Cat('Tom'); 325 assertEqual(Cat, tom.constructor, "bad constructor reference"); 326 assertEqual(Animal, tom.constructor.superclass, 'bad superclass reference'); 327 assertEqual('Tom', tom.name); 328 assertEqual('Tom: meow', tom.say('meow')); 329 assertEqual('Tom: Yuk! I only eat mice.', tom.eat(new Animal)); 330 }}, 331 332 testSupercall: function() { with(this) { 333 var tom = new Cat('Tom'); 334 assertEqual('Tom: Yum!', tom.eat(new Mouse)); 335 }}, 336 337 testAddingInstanceMethod: function() { with(this) { 338 var tom = new Cat('Tom'); 339 var jerry = new Mouse('Jerry'); 340 341 Class.add(Animal, { 342 sleep: function() { 343 return this.say('ZZZ'); 344 } 345 }); 346 347 Class.add(Mouse, { 348 sleep: function() { 349 return this.parent() + " ... no, can't sleep! Gotta steal cheese!"; 350 } 351 }); 352 353 assertEqual('Tom: ZZZ', tom.sleep(), "added instance method not available to subclass"); 354 assertEqual("Jerry: ZZZ ... no, can't sleep! Gotta steal cheese!", jerry.sleep()); 287 355 }} 288 356