extends keyword instead of <superclass ... >
Dmitry A. Soshnikov
dmitry.soshnikov at gmail.com
Mon Mar 28 13:53:07 PDT 2011
On 28.03.2011 0:05, Brendan Eich wrote:
> On Mar 27, 2011, at 11:33 AM, Juan Ignacio Dopazo wrote:
>
>> On Sat, Mar 26, 2011 at 6:31 PM, Dmitry A. Soshnikov
>> <dmitry.soshnikov at gmail.com <mailto:dmitry.soshnikov at gmail.com>> wrote:
>>
>> Why not just to use already reserved `extends` keyword for
>> specifying a superclass? These XML-like braces looks not so elegant.
>>
>>
>> I asked this question a couple of days ago. The answer is quite
>> simple. Object initializer extensions are more than just constructor
>> syntax. They allow you to create complex objects without all
>> the hassle in (function(){}()). So the constructor syntax was made
>> this way to be consistent with object initializer syntax.
>
> The meta syntax (e.g., var obj = {<proto: p>, key: val}) is not
> inconsistent with initialisers, it's an extension to them. But it's
> not the only self-consistent extension. Dmitry mentioned letting the
> meta properties appear to be regular key: value pairs but
> distinguishing the keys with @ or #.
>
> Allen makes the point that class D extends B {...} may look too much
> like languages where it means something quite different. That's true,
> but I am not sure JS should be so special that it seems to mix bits of
> those languages into one (of several conceivable) extensions to
> initialiser syntax:
>
> class D {<superclass B>};
>
> Whatever you think of the meta section, the leading 'class D {'
> telegraphs influence from, and just familiarity with, those other
> languages. And I don't think that is a bad thing even if semantics differ.
>
> Just changing 'class' to 'constructor' (adding a new
> perhaps-only-contextually reserved word, and a long one at that) is
> not the issue. Sure, doing that would in a text-only way make the
> syntax not look like any other language, exactly. But ignore the skin:
> the bones look familiar, going back to C structs.
>
> Now add some notion of inheritance and you're following the C++ "body
> plan".
>
Exactly. "Classes" are not about just the "class" keyword, but about the
_ability to classify_, i.e. to program in classified (i.e. with
object-patterned programming). JS supports (and supported all these
years both approaches: delegation-based prototypal (i.e. unclassified or
chaotic code reuse) and classical (classified or systematized code reuse).
Thus, a "class" in JS is a pair of "constructor function + prototype".
From this viewpoint, e.g. classes in Python (or CoffeeScript) are just
syntactic sugar of the same delegation-based inheritance used in JS. And
this means that JS also may have this sugar -- to allow users to program
in classified manner (if they need to). So there's no a big difference
between these languages and therefore keyword `extends` may fit
absolutely normally.
Here how I see classes syntactic in JS (a combination of Coffee's sugar
+ Java's syntax, since we can't eliminate it).
Notes:
I think that usage of thing like: class method fromString() { .. } are
to verbose.
Don't think we need another keyword `method` at all.
Also I used a syntactic sugar for `this` keyword as `@`. This `at`
allows easily to define and distinguish class- and instance- methods.
The rule is simple: if a property/method inside the class body starts
with @ -- it's the class's property/method (i.e. `this` refers to
class). In other case -- it's an instance method. @ evaluated inside the
instance method refers of course to the instance.
Here's a small example with sugared (on the left hand) and desugared (on
the right hand side) views: http://bit.ly/hvS7hl Take a look please.
And below is just an example without the desugaring. Thus, the definiton
itself is in declarative form. Also I think it's good to provide both
dynamic and static classes. By default I used dynamic classes, so
`static` keyword is explicit.
In the example I also used `include` keyword as an ability to mixin some
module as a direct ancestor of an instance, i.e. before the class in the
hierarchy. Mixins/traits will allow to reuse the code horizontally (not
only with a single vertical inheritance "tower").
/* ------------------------------------------------------
* Class Point definition
* ------------------------------------------------------
*/
class Point {
/**
* Class method (placed on constructor function)
*/
@fromString: function (s) {
return new Point(parse(s));
}
/**
* Instance intializer (aka "constructor")
*/
initialize: function (x, y) {
@move(x, y);
}
/**
* Simple instance method (placed on prototype)
*/
move: function (x, y) {
@x = x;
@y = y;
@repaint();
}
/**
* Class property (placed on constructor function)
*/
@x: 10
}
/* ------------------------------------------------------
* Class Point3D definition
* ------------------------------------------------------
*/
static class Point3D extends Point {
include Comparable;
/**
* Class static property
*/
@instances: []
/**
* Instance intializer (aka "constructor")
*/
initialize: function (x, y, z) {
super(x, y);
@z = z;
@class.instances.push(@); // save the instance
}
}
/* ------------------------------------------------------
* Examples:
* ------------------------------------------------------
*/
// create new 3D point
let point = new 3DPoint(10, 20, 30);
console.log(point); // "[instance 0x1382 of Point3D class]"
// inherited method
point.move(100, 200);
// introspect the class
console.log(point.class); // "[class Point3D]"
console.log(point.class === Point3D); // true
// instrospect the super class
console.log(point.class.super); // "[class Point]"
console.log(point.class.super === Point); // true
console.log(Point3D.super === Point); // true
console.log(point instanceof Point3D); // true
console.log(point instanceof Point); // true
// class method
let p = Point.fromString("10-20");
console.log(p.class); // "[class Point]"
// analyze class methods and properties
console.log(Point.classMethods); // ["fromString"]
console.log(Point.classProperties); // ["x"]
console.log(Point.instanceMethods); // ["move"]
console.log(Point3D.classProperties); // ["instances"]
How does it look like? Do we need such a sugar? For both -- classes and
`this` as `@`? Then # can be used for meta-properties on initialisers.
Dmitry.
> Do we really need to look different yet still have bones that look so
> familiar? I am not convinced.
>
> The strongest case for extending initialiser syntax is that it is
> "nearly declarative" today. That suggests strongly making the
> extension fully declarative, i.e., not usable as an expression. And
> that, all else equal (never is, but:) says to consider class D extends
> B {...}. My 2 cents.
>
> /be
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110329/e8b35602/attachment.html>
More information about the es-discuss
mailing list