Verwijderd schreef op donderdag 12 juni 2008 @ 23:24:
Dat hoeft niet perse, trouwens. Met gewone 'vanilla' prototype-based inheritance kun je gewoon private members blijven gebruiken. (en dan bedoel ik dus niet het "prototype" framework maar de prototype property) de Class.create() varianten verliezen dat inderdaad wel wat voor mij persoonlijk reden genoeg is om ze niet in mijn eigen projecten te gebruiken. Overigens (en dit is een hele andere discussie) kleven er aan private members in JS ook wel wat nadelen. Ze zijn (a) lastiger te debuggen omdat ze niet zichtbaar zijn bij het inspecten van een object of in de script debugger van Firebug en (b) ze zijn niet of via een omweg te unit-testen.
Met "In alle gevallen gaat het gebruik van private members verloren", doelde ik dan ook op de abstractiemethoden. Vandaar ook mijn voorkeur naar het gebruik van puur prototyped inheritance, zodat ik niets aan functionaliteit hoef in te leveren.
Geef eens een voorbeeld? Dat zou namelijk het hele OO-idee onderuit halen.
Sommige van deze implementaties werken door simpelweg eigenschappen te kopiëren naar ervende objecten. Dat maakt misschien wel dat het object overeenkomt met dat waarvan je "erft", maar de objecten hebben verder geen enkele relatie.
Omdat het je code overzichtelijker, compacter en beter onderhoudbaar kan maken. Het kan ook precies het tegenovergestelde doen. Het is maar net hoe je het toepast. Het valt of staat eigenlijk bij je object-model. Ikzelf gebruik eigenlijk alleen maar de bovengenoemde prototypal inheritance en dan zelden meer dan 2 nivo's diep.
Ik heb de behoefte om het duidelijker te maken nooit zo begrepen. Ik bouw zelf m'n objecten (en inheritance) als volgt op:
JavaScript:
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
| /**
* Animal base object
*/
function Animal()
{
// Private
var self = this;
// Public
this.eat = eat;
/**
* Eat something
* @param {Object} food An instance of Food.
*/
function eat(food)
{
// Munch munch
}
}
/**
* Your favorite farm animal
* @inherits Animal
*/
function Cow()
{
// Call the prototype's constructor
Animal.call(this);
// Private
var self = this;
// Public
this.moo = moo;
/**
* Moo?
*/
function moo()
{
// Moo!
}
}
// Inheritance
Cow.prototype = new Animal(); |
Tenzij ik wat over het hoofd zie, is dit vrij helder en is iedere ander aanpak, precies dat. Anders, maar niet per definitie beter.
Ik snap daarom dus ook niet waarom er zo'n focus is in de JS-wereld op die inheritance technieken. Naar mijn mening zijn er veel belangrijkere patterns die veel meer winst opleveren met minder verwarring (zoals bv het publisher/subscriber pattern).
Helemaal mee eens.
crisp schreef op donderdag 12 juni 2008 @ 23:34:
[...]
En daar zou je dan ook de conclusie uit kunnen trekken dat er legio mensen zijn die dan ook liever zien dat het OO-model van javascript meer lijkt op datgene dat ze gewend zijn van andere talen...
Dan zullen ze op ECMAScript 4 moeten wachten. Wrappers rond fundamentele eigenschappen van een taal vind ik het hoe goed bedoeld ook, altijd een verkeerde aanpak.
Men zou je ook raar aankijken als je een Visual Basic achtige wrapper rond C++ gaat schrijven, puur omdat je niet bekend bent met C++. Waarom moeten we JavaScript dan ineens op Ruby of Java laten lijken. Of nog erger, een Toolkit bouwen waarin je in Java kan programmeren, waarna het vertaald wordt naar JavaScript.
Object.extend() is overigens geen abstratie-method maar gewoon een helper method om in 1 keer meerdere prototyped methods toe te kennen (met eventueel een check of een dergelijke method al bestaat)
Nadeel ervan is dat je ook daar je private members verliest, dat is eigenlijk de reden dat ik 'm erbij noemde.