Dmitry - thanks. I really appreciate this detailed answer. Your insight is very valuable.
One thing (and I know you know this of course) python class definition is entirely different from languages like java in which the classes are static - which on the one hand helps to maintain order and our 'mental model' but on the other hand can get very frustrating for those of us who like more dynamic control at runtime. So anyway your later python vs. Js examples would not apply to languages like java One suggestion - it might help to demonstrate the universality of classes if we use the term 'type' (or 'custom type') since such a term is used freely in almost every language Anyway - great post Dmitry On Dec 27, 1:31 am, "Dmitry A. Soshnikov" <[email protected]> wrote: > Yes, Angus, all you said is directly related with JavaScript and is > correct. However, I wanted to underline the idea that concept of a > "class" is not about syntax and a keyword `class` in the language, but > about exactly the _ability to classify_. Ability to classify relates not > even to languages in general, but to the common ability to > _differentiate_. It's used directly and actively in biology for example. > And absolutely in the same respect it's used as an abstraction technique > in the programming. > > We can classify _without_ the `class` keyword. And as I mentioned, > languages which are considered as class-based (Python, CoffeeScript), in > real, are the same delegation/prototype-based as JavaScript and the > `class` keyword is just a _syntactic sugar_. This is was my main > thought. That is, if I want to see in my concrete project a classified > system (a good example is a UI system) why should I accept an > unreasonable "`new` is bad part, avoid it, prototypes are good part" > (seems we stared from this ;) ? > > Below some notes on your notes (I'll use Python to show that there is no > _big_ difference between class-based and prototype-based). > > On 26.12.2010 22:19, Angus Croll wrote: > > > Dmitry - some great points there. > > > A couple of differences between JavaScript's prototypical inheritance > > and classical inheritance: First, prototype assignment is dynamic > > which means custom types and inheritance can be modified at runtimes. > > 1. Definition > > function A() {} // JS > > class A(object): # Python > pass > > 2. Instances > > var a = new A; // JS > > a = A() # Python > > 3. Dynamic augmentation of the class > > A.prototype.x = 10; // JS > > A.x = 10 # Python > > a.x // 10, via delegation -- in both (JS, Py) > > 4. Shadow with own properties > > a.x = 20 > > a.x // 20 -- in both (JS, Py) > > 5. Remove the shadow (own property) > > delete a.x // JS > > del a.x # Python > > a.x // again 10, sic, again via delegation to the class/prototype > > 6. Adding a method dynamically > > A.prototype.foo = function () this.x // JS, 1.8 > > A.foo = lambda self: self.x # Python > > // and new method is again available via delegation > > a.foo(); // 10, JS > > a.foo() # 10, Python > > 7. Change class/prototype dynamically > > // JS > > b = { > bar: function () { > return this.x; > } > > }; > > a.__proto__ = b; > > a.bar(); // new method is available, 10 > > # Python > > class B(object): > def bar(self): > return self.x > > # change a's class > # Remind something? ;) JS got its __proto__ from here. > > a.__class__ = B > > a.bar() # 10, also via delegation new method is available > > 8. Remove explicit links > > delete b; > > a.bar(); // 10, still proto is alive of course > > del B > a.bar() # 10, the same > > 9. Create simply and object: > > a = {x: 10, y: function () { return this.x }}; // JS > > a = {'x': 10, 'foo': lambda: a['x']} # Python > > a.foo(); // 10 > > a['foo']() # Python (JS is more sugared in this case) > > etc. > > > Second true classes > > In truth, there are no concept of "true classes". There are only _local > concrete implementations_. They are separated with: > > (1) second-class static classes (examples: Java, C++) > (2) first-class dynamic classes (examples, Python, Ruby, CoffeeScript, > ECMAScript (without sugar)). > > I had even specially a section devoted to the (2) > --http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/... > > This section was to _correct_ the wide-spread and just wrong meaning > "classes are not needed", "there are no classes". Again, we should > differentiate -- a syntactic sugar (including `class` keyword) and the > _ability to classify_. Regarding JS -- it has no (yet) the syntactic > sugar in a view of `class` keyword, etc, but has in a view of > constructor+proto pair, but has (and always has) the ability to classify > and to program in the classified manner. If needed, of course. If not > needed, JS of course has in its core all the tools for unclassified > (i.e. prototypal) programming. And only a programmer should choose what > is better for his _current_ project. In this project he doesn't need > classes, in that -- he does need. And the statements as "new is bad, > prototypes are good", sorry, just technically incorrect. There should be > understanding of the general programming technique, but not just those > "mystic, available only for esoteric programmers prototypes", which in > real do not even differ much form the classical approach in respect of > the classified programming. > > > do not form part of the object model, whilst in > > JavaScript, everything including custom types are objects > > Yep, this is a fair notice, though, I'd relate it to the exact > implementation. And of course if we speak about only _unclassified_ > programming, then there is a difference between a the classical approach. > > > (except > > primitives blah blah blah). I find the second point can lead to > > obfuscation of custom types in JavaScript and thus requires more > > careful organization and documentation. > > > I'm not wild about JavaScript frameworks defining their own class > > objects. It seems like a lot of overhead to replicate Java/C++ (etc.) > > style > > Probably. Or just a syntactic sugar. Take a look again on CoffeeScript's > sugar for classes. _Inside_ this sugar (and in Python as you saw the > picture is similar) our prototypes and seems there is no a big (it at > all) overhead. A convenience. A struggle against the _complexity_ and > _syntactic noise_ (which deverts us from the main work -- a _mind work_) > _is_ the way and the _main purpose_ of the programming. IMO. > > > concepts where actually prototypical type definition is both > > lean and fairly easy to grasp (once we unload all the stuff we learned > > from other languages). > > Yes, of course and it's true. But what I say: a programmer should > choose. And choose depending on the needs. > > > > > Angus > > > On Dec 25, 11:51 am, "Dmitry A. Soshnikov" > > <[email protected]> wrote: > >> On 25.12.2010 2:46, fernando trasvina wrote: > > >> [...] > > >>> What crockford is trying to point is that you should not think as the > >>> new operator as the classical use of new > >>> you should think of it as the prototype pattern, > >> Yes, but actually, there is no a big difference between "classical new" > >> and "prototypal new" (if I can use such a naming). > > >> In many languages, `new` is just a syntax construct to generate a new > >> object. Usually, not just an object, but the object of a some > >> /classification/. Again, absence or presence of the "class" concept in > >> the languages, does not affect the ability of the language to /create/ > >> and /classify/ objects. > > >> What is a big difference in that how do you call the /sugar/ for > >> /creation/ and /classification/ of your objects? Again, you may sugar it > >> in a special syntax construct and to name it "class". Or you may use the > >> simplest form of the generation -- just a function which creates and > >> returns an object and sets the classification tag (to be able > >> distinguish somehow these object from other with the similar properties). > > >>> and this is not in conflict in any way with the Object.create method > >>> Object.create is good for creating inheritance hierarchies > >>> new is good for creating instances that need an initializer function in > >>> this case known as constructor function. > >> Again, the main difference of the classical and prototypal models in the > >> /classified/ (classical) and /unclassified/ (prototypal) concepts. And > >> all the other differences are not so essential. It's very easy choice > >> (regardless in which system you program): > > >> 1. If you don't need to classify your object(s) (and the whole > >> inheritance hierarchic in case you nave more than one object in it) -- > >> use /unclassified/ pattern (e.g. Object.create). > > >> Indeed, why do you need a class if you just want to use a complex object > >> with some properties and reuse the code (inherit) from another object? > >> Of course prototypal (unclassified) approach is the way. > > >> 2. If you need classified objects -- use /classified/ pattern. In > >> ECMAScript in the simplest way it's achieved via using a /constructors/ > >> (you may use your own factory though). > > >> Really, why do you should use unclassified approach if you decide that > >> /these 100 objects/ are needed to be /grouped/ (classified) by some > >> /sign/? The simplest example again, is a UI button component. > > >>> with the case of super you don't need it because you cannot (even when > >>> there are implementations that provide a way to do it) mutate the proto > >>> attribute of an object, so you always know what object you come from. so > >>> A<- B (B inherits from A) just call A.methodName from B.methodName > >>> A = function(){} > >>> A.prototype.methodName = function(){ > >>> //code > >>> }; > >>> B = function(){} > >>> B.prototype = new A(); // many techniques here to avoid constructor > >>> function being executed if you want to > >>> B.prototype.constructor = B; > >>> B.prototype.methodName = function(){ > >>> //your code > >>> A.prototype.call(this[, ArgumentList]); > >>> }; > >> Having written several such classifications you may want to encapsulate > >> them in some sugar (a meta-constructor e.g. which creates other > >> constructors and sets correctly needed inheritance hierarchy regardless > >> concrete -- A, B, etc, names). > > >>> you should follow the language idioms and not invent new ones because you > >>> don't understand something or because you don't like it, neither because > >>> you are trying to port the idioms from other languages. > >>> well that is my point of view. > >> P.S.: > > >> That's funny, but with JavaScript a one strange thing is happened in its > >> historical way. First (long time ago), programmers (which didn't read > >> the common OOP theory, but just learned the wide-spread C++ > >> implementation with classes) couldn't get quickly the concept of > >> "prototypes" as an /alternative/ OOP paradigm, and as a result named > >> prototypal approach as "not enough serious". > > >> Then who understood the prototypes did IMO (!) a one big mistake. They > >> also (as the first group who didn't clarify OOP > > ... > > read more » -- To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/[email protected]/ To search via a non-Google archive, visit here: http://www.mail-archive.com/[email protected]/ To unsubscribe from this group, send email to [email protected]
