Hi David, Your protected work reminds me a lot of what we did with `namespcase` module in jetpack: https://addons.mozilla.org/en-US/developers/docs/sdk/latest/packages/api-utils/namespace.html Which I also blogged about some time ago: http://jeditoolkit.com/2012/03/15/namespaces.html#post
In contrast to this work though namespaces are not class centric and you can use more than one namespace per object. We also use weak maps to implement that. > I have made obvious by juxtaposing both examples that JavaScript > requires from the programmer to choose between encapsulation and > inheritance. Indeed, as demonstarted above, encapsulation requires a > shared scope. > > I totally agree that with this pain point, but hopefully private names will help this. Still I think that there are other expression problems with classes that could be elegantly solved using clojure like protocols that I have posted other day: http://jeditoolkit.com/2012/03/21/protocol-based-polymorphism.html#post https://mail.mozilla.org/pipermail/es-discuss/2012-March/021603.html Unfortunately I did not got much of a feedback ;) Cool to see others exploring this area! Regards -- Irakli Gozalishvili Web: http://www.jeditoolkit.com/ On Sunday, 2012-04-01 at 15:28 , David Bruant wrote: > Hi, > > A while ago, I posted a challenge on es-discuss [1]. It was a challenge > related to code reuse, modularity and composition. There has been an > interesting suggestion [2] [3] which left me a bit unsatisfied since > relying on constructor arguments while it may not be always possible to > do that. > What I describe as the "protected protocol" is my response to my own > challenge. > Before explaining it, I'd like to take a step back and discuss about the > object oriented properties of JavaScript. > > > Two expected properties of object-oriented languages are encapsulation > and inheritance. > > Encapsulation allows to define objects which can only be interacted with > through a given an interface, thus hiding implementation details. In the > long run, encapsulation makes the maintenance of components easier since > the implementation of an object can be changed without affecting its > clients. > > Encapsulation can be implemented in JavaScript. One usual way is to do > as follow: > > function Storage(){ > var array = Array.prototype.slice.call(arguments, 0); > > return { > add: function(e){ > array.push(e); > }, > read: function(i){ > return array[+i]; > } > }; > } > > Here, access to the array is restricted to the interface ("add" and > "read" methods). > > > Inheritance allows to better reuse code by specializing classes. > This can be implemented as well, usually with this pattern: > > function Storage(){ > this.array = Array.prototype.slice.call(arguments, 0); > } > > Storage.prototype = { > add: function(e){ > this.array.push(e); > }, > read: function(i){ > return this.array[+i]; > } > }; > > > function StorageWithDeletion(){ > Storage.call(this); // equivalent to "super"; > } > > StorageWithDeletion.prototype = Object.create(Storage.prototype); > StorageWithDeletion.prototype.delete = function(i){ > delete this.array[+i]; > }; > > > To define a storageWithDeletion, there is no need to redefine the add > and read method. To extend Storage, StorageWithDeletion here only needs > access to the Storage function in the global scope (or Storage module > when these will be deployed). This has the nice property that Storage > and StorageWithDeletion can be defined in different files since they > don't need to share a common function scope > > I have made obvious by juxtaposing both examples that JavaScript > requires from the programmer to choose between encapsulation and > inheritance. Indeed, as demonstarted above, encapsulation requires a > shared scope. > > Solutions where Storage and StorageWithDeletion would be defined with a > shared scope could be explored, but it would require to define both in > the same file, which, I don't want to be a necessity. > > The trick of the protected protocol is that encapsulation does not > really require a shared scope, it's just the most natural way to do it > in JavaScript. > > When a method located in the prototype chain of an object is called, its > 'this' references the object from which the method has been called. > Programmers have naturally stored the state of an object as own (public) > properties of the object as it's the most natural way to bind > information to an object. > It doesn't have to be this way, though. WeakMaps offer an > straightforward API to bind information to an object and it is not > necessary to share this WeakMap with the rest of the world. > > > The protected protocol and an example of how to use it can be found at > [4] (which is a bit different than a version I tweeted earlier [5]). > > The most important part in my opinion is that the Person.js and > ComputerSavvyPerson.js are defined in 2 different files. The only thing > the latter needs is a reference to the constructor it inherits from > (here, Person). > > Things that are expected to be secret can be kept as such. First, a > Person's secret doesn't leak, second, even a ComputerSavvyPerson's > secret doesn't leak. A bit more tricky was to make that defining a new > subclass doesn't leak secrets of the base class. > > In my opinion, the boilerplate code for this to work is minimal enough, > but I'm interesting on feedback on this aspect. Regardless, the code of > the constructor and of the prototype methods are clean of boilerplate > code and only require to use the "Protected(this)" convention when > intending to work with private-to-the-inheritance-tree parts of the > object-state. > > The implementation of the 2 necessary functions take 60 lines which is > rather reasonable. > > So all the properties I expected are here. On the negative side, > prototype object equality had to be broken for the sake of preventing > leaks of "protected" properties, so instanceof is necessarily broken. I > think it's not a big deal since I could reimplement one myself if really > necessary. > > It's ready for private names and these would need to be defined inside > the "declaration code" in order for them not to leak outside. > I intuit that assuming class syntax can be embedded in a function, I > could wrap it and add support for the Protected convention if I want to. > > Anecdotes: > 1) In Person.js, I've been burned by non-lexical this when writing the > code that increased the age over time. We really need functions with > lexical this :-) > 2) After some feedback by Brendan on Twitter, I've created a > WeakMap.prototype.getset function following a discussion we had on > es-discuss about setting a value when there is not already one. > > > I'm interested in any feedback, opinions or questions you'd have. > > Thanks, > > David > > [1] https://mail.mozilla.org/pipermail/es-discuss/2012-March/021292.html > [2] https://mail.mozilla.org/pipermail/es-discuss/2012-March/021304.html > [3] https://gist.github.com/2053624 > [4] https://gist.github.com/2279059 > [5] > https://gist.github.com/c7d4947b41936680810d/a531bd4412b67dc0fed180d1d776314bf8c4747b > _______________________________________________ > es-discuss mailing list > [email protected] (mailto:[email protected]) > https://mail.mozilla.org/listinfo/es-discuss > >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

