-
Notifications
You must be signed in to change notification settings - Fork 0
/
Base.js
337 lines (280 loc) · 7.15 KB
/
Base.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
/**
* Define our base class, complete with:
* private properties,
* priveledged functions,
* public functions,
* official getters and setters
*
* @this Base
* @constructor
* @param {number} x The x.
* @param {number} y The y.
* @param {string} name The name.
*/
var Base = function(x, y, name) {
// Private properties
var x_,
y_,
name_;
// Priveleged method can access the private stuff
// Notice we override this in one of the child classes
this.renderProperties = function() {
console.log('this: ', this);
console.log('x: ', x_);
console.log('y: ', y_);
console.log('name: ', name_);
};
// Define our getters and setters
this.addProperties({
x: {
get: function() {
return x_;
},
set: function(val) {
x_ = val;
}
},
y: {
get: function() {
return y_;
},
set: function(val) {
y_ = val;
}
},
name: {
get: function() {
return name_;
},
set: function(val) {
name_ = val;
}
},
length: {
get: function() {
return Math.sqrt((x_ * x_) + (y_ + y_));
}
}
});
// Initialize attributes
this.init(x, y, name);
};
/**
* Render this object as a string
*
* @return {string} Object rendered as string.
*/
Base.prototype.toString = function() {
var s = this.name + ' = {x:' + this.x +
', y:' + this.y +
', length:' + this.length + '}';
return s;
};
/**
* Init this object
* Called by the constructor
* Notice that children can override this function and call
* the Base init using the 'uber' method.
*
* @param {number} x The x.
* @param {number} y The y.
* @param {string} name The name.
*/
Base.prototype.init = function(x, y, name) {
this.x = x || 0;
this.y = y || 0;
this.name = name || 'Base';
};
////////////////////////////////////////////////////////////////////////////////
/**
* Classical Inheritance using Crawford's sugar functions
* http://bit.ly/crawford-inheritance.
*
* This child adds getters and setters before inheriting from parent
* The next child example shows adding getters/setters after inheritance
*
* @this Child
* @extends {Base}
*
* @param {number} x The x.
* @param {number} y The y.
* @param {number} w The w.
* @param {number} h The h.
* @param {string} name The name.
*/
function Child(x, y, w, h, name) {
var width_,
height_;
this.addProperties({
width: {
get: function() {
return width_;
},
set: function(val) {
width_ = val;
}
},
height: {
get: function() {
return height_;
},
set: function(val) {
height_ = val;
}
}
});
this.init(x, y, w, h, name);
}
// Inherit from our parent class
Child.inherits(Base);
// Override the toString function
Child.method('toString', function() {
var s = this.name + ' = {x:' + this.x + ', y:' + this.y +
', width:' + this.width +
', height:' + this.height +
', length:' + this.length + '}';
return s;
});
// Extend the init function.
// Be sure to call the parent init via uber
Child.method('init', function(x, y, w, h, name) {
this.uber('init', x, y, name);
this.height = h || 0;
this.width = w || 0;
});
////////////////////////////////////////////////////////////////////////////////
/**
* Classical Inheritance v2 using Crawford's sugar functions
* http://bit.ly/crawford-inheritance
*
* This child adds getters and setters after inheriting from parent
* The previous child example shows adding getters/setters before inheritance
*
* @this Child2
* @extends {Base}
*
* @param {number} x The x.
* @param {number} y The y.
* @param {number} w The w.
* @param {number} h The h.
* @param {string} name The name.
*/
function Child2(x, y, w, h, name) {
var width_,
height_,
name_; // notice this is never used because we're setting the parent
// Priveleged method can access the private stuff
// notice that this was defined in Base class, which
// we inherit from later. The parent function is
// accessed via the .uber() method.
this.renderProperties = function() {
console.log('------------------\n',
'parent.renderProperties: ');
this.uber('renderProperties');
console.log('------------------');
console.log('My renderProperties:');
console.log('this: ', this);
console.log('Notice that we do not have access to name_ here',
' because the setter is defined on the parent class',
' and we set it using the parent\'s constructor.',
' So we must access it via the getter\n\n',
'Alternatively, we could redefine the "name" setter/getter',
' so we would have access to the private name_ here');
console.log('name_: ', name_);
console.log('this.name: ', this.name);
console.log('width: ', this.width);
console.log('height: ', this.height);
console.log('------------------');
};
this.init(x, y, w, h, name);
}
// Inherit from our parent class
Child2.inherits(Base);
// Add all getter/setter properties
Child2.addProperties({
width: {
get: function() {
return width_;
},
set: function(val) {
width_ = val;
}
},
height: {
get: function() {
return height_;
},
set: function(val) {
height_ = val;
}
}
});
// Override the toString function
Child2.method('toString', function() {
var s = this.name + ' = {x:' + this.x + ', y:' + this.y +
', width:' + this.width +
', height:' + this.height +
', length:' + this.length + '}';
return s;
});
// Extend the init function.
// Be sure to call the parent init via uber
Child2.method('init', function(x, y, w, h, name) {
this.uber('init', x, y, name);
this.height = h || 0;
this.width = w || 0;
});
////////////////////////////////////////////////////////////////////////////////
/**
* Parasitic Inheritance
* http://www.crockford.com/javascript/inheritance.html
*
* Pros: all code contained within the Parasite wrapper function
* Cons: it can only be extended new child clases via parasitic inheritance.
* we cannot access that.prototype because it's private to the class
*
* @this Parasite
* @extends {Base}
*
* @param {number} x The x.
* @param {number} y The y.
* @param {number} w The w.
* @param {number} h The h.
* @return {Parasite} A new Parasite object.
*/
function Parasite(x, y, w, h) {
var width_,
height_,
that = new Base(x, y, 'Parasite');
that.addProperties({
width: {
get: function() {
return width_;
},
set: function(val) {
width_ = val;
}
},
height: {
get: function() {
return height_;
},
set: function(val) {
height_ = val;
}
}
});
// Override a function
that.toString = function() {
var s = this.name + ' = {x:' + this.x +
', y:' + this.y +
', width:' + this.width +
', height:' + this.height +
', length:' + this.length + '}';
return s;
};
// Initialize attributes
that.height = h || 0;
that.width = w || 0;
return that;
}